IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【Linux】多线程的概念 -> 正文阅读

[数据结构与算法]【Linux】多线程的概念

准备

博主:大大怪先森(记得关注,下次不要迷路哦)
编程环境:xshell(点击下载)
所示代码:码源

在这里插入图片描述


前言

本文将讲解多线程的基本概念!!!


提示:以下是本篇文章正文内容

一、基本概念

线程:在进程内部运行的一个执行流分支(执行流),属于进程的一部分,粒度比进程更细和更轻量化。

二、可重入函数

在这里插入图片描述

  • main函数调用insert函数向一个链表head中插入节点node1,插入操作分为两步,刚做完第一步的 时候,因为硬件中断使进程切换到内核,再次回用户态之前检查到有信号待处理,于是切换 到sighandler函
    数,sighandler也调用insert函数向同一个链表head中插入节点node2,插入操作的 两步都做完之后从
    sighandler返回内核态,再次回到用户态就从main函数调用的insert函数中继续 往下执行,先前做第一步
    之后被打断,现在继续做完第二步。结果是,main函数和sighandler先后 向链表中插入两个节点,而最后只有一个节点真正插入链表中了。
  • 像上例这样,insert函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入,insert函数访问一个全局链表,有可能因为重入而造成错乱,像这样的函数称为 不可重入函数,之,如果一个函数只访问自己的局部变量或参数,则称为可重入(Reentrant) 函数。想一下,为什么两个不的控制流程调用同一个函数,访问它的同一个局部变量或参数就不会造成错乱?

如果符合一下任意一个条件就是补课重入函数:

  • 调用了malloc或free,因为malloc也是用全局链表来管理堆的。
  • 调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构

三、可重入

3.1常见的不可重入的情况

  • 调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的
  • 调用了标准I/O库函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构
  • 可重入函数体内使用了静态的数据结构

3.2常见的可重入的情况

  • 不使用全局变量或静态变量
  • 不使用用malloc或者new开辟出的空间
  • 不调用不可重入函数
  • 不返回静态或全局数据,所有数据都有函数的调用者提供
  • 使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数

四、volatile关键字

#include<stdio.h>
#include<string.h>

volatile int flag = 0;

void handler(int signo)
{
  flag = 1;
  printf("change flag 0 to 1\n");
}
int main()
{
  signal(2,handler);
  while(!flag);
  printf("这个进程是正常退出的!\n");
  return 0;
}

在这里插入图片描述

volatile 作用:保持内存的可见性,告知编译器,被该关键字修饰的变量,不允许被优化,对该变量
的任何操作,都必须在真实的内存中进行操作


五、的线程和进程

如下图:
在这里插入图片描述
我们会发现线程相对于我们之前所学习的进程就是多了更多的进程控制块(pcb),之前进程内部只有一个执行流,但是今天的进程却是有多个执行流,进程承担着分配资源的成本,而线程只是cpu调度的基本单位,在创建线程的过程成本是远远低于创建进程的。

5.1进程和线程

  • 进程是资源分配的基本单位
  • 线程是调度的基本单位
  • 线程共享进程数据,但也拥有自己的一部分数据:
    线程ID
    一组寄存器

    errno
    信号屏蔽字
    调度优先级

进程的多个线程共享 同一地址空间,因此Text Segment、Data Segment都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:

  • 文件描述符表
  • 每种信号的处理方式(SIG_ IGN、SIG_ DFL或者自定义的信号处理函数)
  • 当前工作目录
  • 用户id和组id

5.2代码实现

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<pthread.h>
  4 void* thread_run(void* args)
  5 {
  6   const char* id = (const char*) args;
  7   while(1)
  8   {
  9     printf("I am a %s pthread.c:%d\n",id,getpid());                                                                                                                               
 10     sleep(1);
 11   }
 12 }
 13 int main()
 14 {
 15   pthread_t tid;
 16   pthread_create(&tid,NULL,thread_run,(void*)"thread 1");
 17 
 18   while(1)
 19   {
 20     printf("I am a main pthread.c,%d\n",getpid());
 21     sleep(1);
 22   }
 23   return 0;
 24 }

结果展示:
在这里插入图片描述

总结

希望本篇文章能给各位带来帮助,如有不足还请指正!!!
码字不易,各位大大给个收藏点赞吧!!!

宝子们,点赞,支持。
三连走一波!!!
在这里插入图片描述

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-06-14 22:53:04  更:2022-06-14 22:53:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 1:24:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码