Linux基础08(Linux上的多线程编程)

本文详细探讨了Linux上多线程编程,包括线程概念、用户级与内核级线程比较、Linux线程库操作、数据共享与同步机制(如互斥锁、信号量、条件变量)、线程安全问题及解决策略,以及线程与fork的关系。通过实例演示和实践技巧,帮助读者理解和掌握Linux多线程编程技术。
摘要由CSDN通过智能技术生成

第八章、Linux上的多线程编程

1.线程的概念(总述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

多线程:一个主线程两个函数线程
在这里插入图片描述
Q:进程和线程的区别?
**进程:**在linux系统中,操作系统为每个进程分配4G的虚拟地址内存空间
**线程:**是进程内部的,每个线程都会占用一个栈
在这里插入图片描述
类比关系:
在这里插入图片描述

2.线程的实现方式

在这里插入图片描述
在这里插入图片描述

1.用户级线程(从哲学层次看操作系统)

在这里插入图片描述
优缺点:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.内核级线程

在这里插入图片描述
优缺点:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.组合级线程

4.Linux系统上线程的实现方式

其实就是内核级线程
创建线程和创建进程内核调用的方法是一致的,只是传递的参数标记不同。
在这里插入图片描述
在这里插入图片描述

5.线程和进程的区别

在这里插入图片描述

3.Linux上线程的使用

1.线程库中的方法介绍与使用

在这里插入图片描述

1.1线程创建

线程方法的实现实是在专有的线程库中
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
问题:undefined,因为头文件里是声明
在这里插入图片描述
加一个动态库的方法
在这里插入图片描述
ldd查看一下
在这里插入图片描述
结果
在这里插入图片描述
结论:
在这里插入图片描述

1.2线程函数的传参

在这里插入图片描述

1.2.1值传递实例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.2.2地址传递

在这里插入图片描述在这里插入图片描述

2.线程并发

在这里插入图片描述
在这里插入图片描述结果:
在这里插入图片描述
原因:
线程是并发执行的,有可能两个线程是同时执行的,比如g本来是1,两个线程同时执行,在内存中取值1,然后都对1加了一次,都变成了2,又写入内存。效果就是只加了一次

5.Q:让主线程比线程函数的执行时间短

重点:结束线程的方法十分重要
在这里插入图片描述
在这里插入图片描述
原因
在这里插入图片描述
结束线程方法的使用:
在这里插入图片描述
在这里插入图片描述
等待线程结束方法的使用:会变成串行执行了,所以一般不常使用

在这里插入图片描述
在这里插入图片描述

3.验证线程之间的数据共享

.data .bss数据段 和 .heap堆区
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结果
在这里插入图片描述
内核:文件描述符
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结论:任何一个线程打开的文件在其他线程中可以访问,即共享文件描述符

4.线程同步

与进程同步的目的相同
1.在访问临界资源时需要同步(间接制约关系
2.要相互配合着执行(直接制约

1.互斥锁(互斥量)

在这里插入图片描述
在这里插入图片描述

1.1例1:aaaaabbbb

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结果
在这里插入图片描述

2.信号量(线程级的信号量)

进程是由操作系统控制的,所以使用的方法我们需要自己封装。
而线程这边的方法是由线程库提供的,库里已经给我们封装好了方法,不需要我们自己动手了。

在这里插入图片描述
在这里插入图片描述

2.1例1:主进程获取用户数据输入,函数线程将用户输入的数据存储到a.txt中

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

3.条件变量:为多个线程提供了一个汇合场所

条件变量提供了一种线程间的通知机制:当某个共享数据达到某个值的时候,唤醒等待这个共享数据的线程。
在这里插入图片描述

4.读写锁

在这里插入图片描述
在这里插入图片描述

5.线程安全

一个好博文
在这里插入图片描述
线程安全的解决方式:
1.使用线程同步(eg.在函数线程 开始和结束前,加互斥锁)
2.不使用共享的数据

在这里插入图片描述
函数线程的栈区
在这里插入图片描述
== buff在主线程的栈区==
在这里插入图片描述
在这里插入图片描述
结果:
在这里插入图片描述
Q:为什么主线程能看见函数线程的buff?
stork方法要记录数据,下次切割还能记得,所以数据的存储位置必定不能在该函数的栈区,不然调用完就销毁了,所以数据应该保留在.data或者.bss数据区,所以线程又不安全了
在这里插入图片描述
用stork_r方法可以解决安全问题
在这里插入图片描述
在这里插入图片描述
结果:
在这里插入图片描述
在这里插入图片描述

5.1线程安全问题举例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结果不确定:
**原因:**执行++如果是串行执行肯定是10000,由于是并行运行了,所以出现值不确定的问题,因此要考虑线程安全
在这里插入图片描述

6.线程与fork

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
atfork注册这三个方法,以及其调用时机,都是为了保证在fork执行过程中,所有的锁都是加锁状态的。没有其他线程会加锁成功。fork完成之后, 再主动对所有的锁,分别在父进程空间和子进程空间解锁。fork之后, 父好进程的使用的锁都是解锁状态的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值