csapp 第十二章 并发编程
并发编程
什么是并发?我们可以这样理解就是同时运行,做多件事情,比如,我们在看剧的同时,吃着薯片,像这种,在时间上重叠的现象,就是并发、
并发的作用
访问慢速i\o设备。访问慢速的i\o设备的时候,内核可以同时运行一些其他的数据,来等待。
与人进行交互。我们一般打开电脑,都会同时运行好几个程序。
服务器服务多个网络客户端。
在多核机器上进行并行计算。
多线程运行。
基于进程的并发编程
基于进程的并发服务器
![image-20230226165229824](csapp 第十二章 并发编程/image-20230226165229824.png)
![image-20230227143648282](csapp 第十二章 并发编程/image-20230227143648282.png)
优点:具有共享文件表,但并不共享用户地址空间,进程有 独立的地址空间。这样使得一个进程不可能不小小覆盖另一个进程调出虚拟内存。
缺点:独立的地址空间使得进程之间的通信变得更加困难,从而造成它们往往比较慢,控制进程和IPC的开销比较大。
关于IPC的解释
![image-20230227144750118](csapp 第十二章 并发编程/image-20230227144750118.png)
基于线程的并发编程
线程与进程的区别:1、线程运行的消耗比进程的消耗要小。2、对于进程来说,创建一个新的进程,新和旧的关系为父子关系。而在同一个进程中创建线程池,它们之间的关系都为对等,就算是主线程,也仅仅是代表它是进程中第一个运行的线程。
线程池的一个特点就是,一个线程可以杀死它的任何对等的线程,或者等待对等线程终止。而且和进程一样,对等线程都能够读写相同的共享数据。
分离线程
在任何一个时间点上,线程都是可结合或者是可分离的。其中可结合线程能够被其他线程回收和杀死,在被其他的线程回收之前,它的内存资源,是不会被释放的。而分离线程是不能够被其他线程回收或者杀死的。它的内存资源,在它终止时由系统自动释放。
![image-20230228125255617](csapp 第十二章 并发编程/image-20230228125255617.png)
多线程程序中的共享变量
线程内存模型
一组线程并发的运行在一个进程的运行上下文中。每个线程都有他自己独立的线程上下文,也就是运行环境。每个线程共享进程上下文的剩余部分。包括:用户的虚拟地址空间等。但是线程的寄存器是不会进行共享的。
线程安全
四个线程不安全的函数类
加锁–复制技术
- ![image-20230301205637003](csapp 第十二章 并发编程/image-20230301205637003.png)
加锁–复制技术的缺点
![](csapp 第十二章 并发编程/image-20230301205824372.png)
死锁
信号量有一种潜在的运行时错误,叫死锁。指的是一组线程被阻塞了,等待一个永远不会为真的条件。打个比方,一套工具分给几个人使用,每个人将活干完之后,才会将工具归还,按照正常来管理,这些分工具给不同的的人使用,然后等他使用完后,再给另一个人,但是有些时候意外情况会发生,比如,工具有a,b,c,工人有甲乙两人。甲用了工具a,和工具c,乙正在运用工具b,这个时候,甲需要用工具b才能继续工作下去,甲于是就等着乙工作完,然后拿工具。而乙工作到一半,需要a,工具才能继续工作下去,所以乙就等着甲工作完拿a,于是乎,两个都在等待另一方工作完,两人都不进行工作,这样就形成了死锁。