准备 博主:大大怪先森(记得关注,下次不要迷路哦)
编程环境:xshell(点击下载)
所示代码:码源
文章图片
文章目录
- 准备
- 前言
- 一、基本概念
- 二、可重入函数
- 三、可重入
-
- 3.1常见的不可重入的情况
- 3.2常见的可重入的情况
- 四、volatile关键字
- 五、的线程和进程
-
- 5.1进程和线程
- 5.2代码实现
- 总结
前言
本文将讲解多线程的基本概念!!!
提示:以下是本篇文章正文内容
一、基本概念
线程:在进程内部运行的一个执行流分支(执行流),属于进程的一部分,粒度比进程更细和更轻量化。二、可重入函数
文章图片
如果符合一下任意一个条件就是补课重入函数:
- main函数调用insert函数向一个链表head中插入节点node1,插入操作分为两步,刚做完第一步的 时候,因为硬件中断使进程切换到内核,再次回用户态之前检查到有信号待处理,于是切换 到sighandler函
数,sighandler也调用insert函数向同一个链表head中插入节点node2,插入操作的 两步都做完之后从
sighandler返回内核态,再次回到用户态就从main函数调用的insert函数中继续 往下执行,先前做第一步
之后被打断,现在继续做完第二步。结果是,main函数和sighandler先后 向链表中插入两个节点,而最后只有一个节点真正插入链表中了。- 像上例这样,insert函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入,insert函数访问一个全局链表,有可能因为重入而造成错乱,像这样的函数称为 不可重入函数,之,如果一个函数只访问自己的局部变量或参数,则称为可重入(Reentrant) 函数。想一下,为什么两个不的控制流程调用同一个函数,访问它的同一个局部变量或参数就不会造成错乱?
三、可重入 3.1常见的不可重入的情况
- 调用了malloc或free,因为malloc也是用全局链表来管理堆的。
- 调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构
3.2常见的可重入的情况
- 调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的
- 调用了标准I/O库函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构
- 可重入函数体内使用了静态的数据结构
四、volatile关键字
- 不使用全局变量或静态变量
- 不使用用malloc或者new开辟出的空间
- 不调用不可重入函数
- 不返回静态或全局数据,所有数据都有函数的调用者提供
- 使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数
#include
#includevolatile 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 作用:保持内存的可见性,告知编译器,被该关键字修饰的变量,不允许被优化,对该变量五、的线程和进程
的任何操作,都必须在真实的内存中进行操作
如下图:5.1进程和线程
文章图片
我们会发现线程相对于我们之前所学习的进程就是多了更多的进程控制块(pcb),之前进程内部只有一个执行流,但是今天的进程却是有多个执行流,进程承担着分配资源的成本,而线程只是cpu调度的基本单位,在创建线程的过程成本是远远低于创建进程的。
进程的多个线程共享 同一地址空间,因此Text Segment、Data Segment都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:
- 进程是资源分配的基本单位
- 线程是调度的基本单位
- 线程共享进程数据,但也拥有自己的一部分数据:
线程ID
一组寄存器
栈
errno
信号屏蔽字
调度优先级
5.2代码实现
- 文件描述符表
- 每种信号的处理方式(SIG_ IGN、SIG_ DFL或者自定义的信号处理函数)
- 当前工作目录
- 用户id和组id
1 #include.h>
2 #include
3 #include
4 void* thread_run(void* args)
5 {
6const char* id = (const char*) args;
7while(1)
8{
9printf("I am a %s pthread.c:%d\n",id,getpid());
10sleep(1);
11}
12 }
13 int main()
14 {
15pthread_t tid;
16pthread_create(&tid,NULL,thread_run,(void*)"thread 1");
17
18while(1)
19{
20printf("I am a main pthread.c,%d\n",getpid());
21sleep(1);
22}
23return 0;
24 }
结果展示:
文章图片
总结
希望本篇文章能给各位带来帮助,如有不足还请指正!!!
码字不易,各位大大给个收藏点赞吧!!!
【linux|【Linux】多线程的概念】宝子们,点赞,支持。
三连走一波!!!
文章图片
推荐阅读
- 服务器|Linux中进程间通信
- vim|linux的基本开发工具(vim,gcc,gdb,make/Makefile)
- 运维|centos8报错(Errors during downloading metadata for repository ‘base‘)
- centos|docker 安装mysql5.7
- linux禁用CPU 禁用cpu内核
- 【Git】常用操作
- tomcat|开发者,10分钟学会Tomcat ()
- linux命令测网速
- Linux的用户和用户组管理