课本阅读 6小时
整理笔记 3小时html
课本阅读 7小时
整理笔记 5小时程序员
一、并发:逻辑控制流在时间上重叠
二、并发程序:使用应用级并发的应用程序称为并发程序。
三、三种基本的构造并发程序的方法:编程
(1)进程,用内核来调用和维护,有独立的虚拟地址空间,显式的进程间通讯机制。
(2)I/O多路复用,应用程序在一个进程的上下文中显式的调度控制流。逻辑流被模型化为状态机。
(3)线程,运行在一个单一进程上下文中的逻辑流。由内核进行调度,共享同一个虚拟地址空间。安全
一、构造并发服务器的天然方法就是,在父进程中接受客户端链接请求,而后建立一个新的子进程来为每一个新客户端提供服务。
二、由于父子进程中的已链接描述符都指向同一个文件表表项,因此父进程关闭它的已链接描述符的拷贝是相当重要的,并且由此引发的存储器泄露将最终消耗尽可用的存储器,使系统崩溃。服务器
基于进程的并发echo服务器的重点内容网络
(1)须要一个SIGCHLD处理程序,来回收僵死子进程的资源。
(2)父子进程必须关闭各自的connfd拷贝。对父进程尤其重要,以免存储器泄露。
(3)套接字的文件表表项中的引用计数,直到父子进程的connfd都关闭了,到客户端的链接才会终止。多线程
注意:进程的模型:共享文件表,但不是共享用户地址空间。 优势:一个进程不可能不当心覆盖两一个进程的虚拟存储器。
缺点:独立的地址空间使得进程共享状态信息变得更加困难。进程控制和IPC的开销很高。并发
Unix IPC是指全部容许进程和同一台主机上其余进程进行通讯的技术,包括管道、先进先出(FIFO)、系统V共享存储器,以及系统V信号量。函数
一、echo服务器必须响应两个相互独立的I/O时间:
(1)网络客户端发起链接请求(2)用户在键盘上键入命令行。
二、I/O多路复用技术的基本思路:使用select函数,要求内核挂起进程,只有在一个或多个I/O事件发生后,才将控制返回给应用程序。
三、将描述符集合当作是n位位向量:b(n-1),……b1,b0
每一个位bk对应于描述符k,当期仅当bk=1,描述符k才代表是描述符集合的一个元素。能够作如下三件事:
(1)分配它们;(2)将一个此种类型的变量赋值给另外一个变量;(3)用FDZERO、FDSET、FDCLR和FDISSET宏指令来修改和检查它们。
四、echo函数:未来自科幻段的每一行回送回去,直到客户端关闭这个连接。学习
一、状态机就是一组状态、输入事件和转移,转移就是将状态和输入时间映射到状态,自循环是同一输入和输出状态之间的转移。
事件驱动器的设计优势:
(1)比基于进程的设计给了程序员更多的对程序行为的控制
(2)运行在单一进程上下文中,所以,每一个逻辑流都能访问该进程的所有地址空间,使得流之间共享数据变得很容易。
(3)不须要进程上下文切换来调度新的流。
缺点:
(1)编码复杂
(2)不能充分利用多核处理器
粒度:每一个逻辑流每一个时间片执行的指令数量。并发粒度就是读一个完整的文本行所须要的指令数量。
一、线程:运行子啊进程上下文中的逻辑流。
二、线程有本身的线程上下文,包括一个惟一的整数线程ID、栈、栈指针、程序计数器、通用目的寄存器和条件码。全部运行在一个进程里的线程共享该进程的整个虚拟地址空间。
一、主线程:每一个进程开始生命周期时都是单一线程。
对等线程:某一时刻,主线程建立的对等线程
二、线程与进程的不一样:
(1)线程的上下文切换要比进程的上下文切换快得多;
(2)和一个进程相关的线程组成一个对等池,独立于其余线程建立的线程。
(3)主线程和其余线程的区别仅在于它老是进程中第一个运行的线程。
三、对等池的影响
(1)一个线程能够杀死它的任何对等线程;
(2)等待它的任意对等线程终止;
(3)每一个对等线程都能读写相同的共享资源。
线程例程:线程的代码和本地数据被封装在一个线程例程中。每个线程例程都以一个通用指针做为输入,并返回一个通用指针。
pthread create函数建立一个新的线程,并带着一个输入变量arg,在新线程的上下文中运行线程例程f。新线程能够经过调用pthread _self函数来得到本身的线程ID。
一个线程的终止方式:
(1)当顶层的线程例程返回时,线程会隐式的终止;
(2)经过调用pthread _exit函数,线程会显示地终止。若是主线程调用pthread _exit,它会等待全部其余对等线程终止,而后再终止主线程和整个进程。
pthread _join函数会阻塞,直到线程tid终止,回收已终止线程占用的全部存储器资源。pthread _join函数只能等待一个指定的线程终止。
一、在任何一个时间点上,线程是可结合的或者是分离的。一个可结合的线程可以被其余线程收回其资源和杀死;一个可分离的线程是不能被其余线程回收或杀死的。它的存储器资源在它终止时有系统自动释放。
二、默认状况下,线程被建立成可结合的,为了不存储器漏洞,每一个可集合的线程都应该要么被其余进程显式的回收,要么经过调用pthread _detach函数被分离。
pthread _once函数容许初始化与线程例程相关的状态。
once _control变量是一个全局或者静态变量,老是被初始化为PTHREAD _ONCE _INIT.
对等线程的赋值语句和主线程的accept语句之间引入了竞争。
一、每一个线程和其余线程一块儿共享进程上下文的剩余部分。包括整个用户虚拟地址空间,是由只读文本、读/写数据、堆以及全部的共享库代码和数据区域组成的。线程也共享一样的打开文件的集合。 二、任何线程均可以访问共享虚拟存储器的任意位置。寄存器是从不共享的,而虚拟存储器老是共享的。
一、全局变量:虚拟存储器的读/写区域只会包含每一个全局变量的一个实例。
二、本地自动变量:定义在函数内部但没有static属性的变量。
三、本地静态变量:定义在函数内部并有static属性的变量。
变量v是共享的,当且仅当它的一个实例被一个以上的线程引用。
一、共享变量引入了同步错误的可能性。
二、线程i的循环代码分解为五部分:
Hi:在循环头部的指令块
Li:加载共享变量cnt到寄存器%eax的指令,%eax表示线程i中的寄存器%eax的值
Ui:更新(增长)%eax的指令
Si:将%eaxi的更新值存回到共享变量cnt的指令
Ti:循环尾部的指令块。
一、进度图将指令执行模式化为从一种状态到另外一种状态的转换。转换被表示为一条从一点到相邻点的有向边。合法的转换是向右或者向上。
二、临界区:对于线程i,操做共享变量cnt内容的指令构成了一个临界区。
三、互斥的访问:确保每一个线程在执行它的临界区中的指令时,拥有对共享变量的互斥的访问。
四、安全轨迹线:绕开不安全区的轨迹线
不安全轨迹线:接触到任何不安全区的轨迹线就叫作不安全轨迹线
五、任何安全轨迹线都能正确的更新共享计数器。
一、当有多个线程在等待同一个信号量时,你不能预测V操做要重启哪个线程。
二、信号量不变性:一个正在运行的程序毫不能进入这样一种状态,也就是一个正确初始化了的信号量有一个负值。
一、二元信号量:将每一个共享变量与一个信号量s联系起来,而后用P(S)和V(s)操做将这种临界区包围起来,这种方式来保护共享变量的信号量。
二、互斥锁:以提供互斥为目的的二元信号量
加锁:一个互斥锁上执行P操做称为对互斥锁加锁,执行V操做称为对互斥锁解锁。对一个互斥锁加了锁但尚未解锁的线程称为占用了这个互斥锁。
计数信号量:一个呗用做一组可用资源的计数器的信号量
一、信号量的做用:(1)提供互斥(2)调度对共享资源的访问 二、生产者—消费者问题:生产者产生项目并把他们插入到一个有限的缓冲区中,消费者从缓冲区中取出这些项目,而后消费它们。
三、读者—写者问题:
(1)读者优先,要求不让读者等待,除非已经把使用对象的权限赋予了一个写者。
(2)写者优先,要求一旦一个写者准备好能够写,它就会尽量地完成它的写操做。
(3)饥饿就是一个线程无限期地阻塞,没法进展。
写顺序程序只有一条逻辑流,写并发程序有多条并发流,并行程序是一个运行在多个处理器上的并发程序。并行程序的集合是并发程序集合的真子集。
一、线程安全:当且仅当被多个并发线程反复地调用时,它会一直产生正确的结果。
线程不安全:若是一个函数不是线程安全的,就是线程不安全的。
二、线程不安全的类:
(1)不保护共享变量的函数
(2)保持跨越多个调用的状态的函数。
(3)返回指向静态变量的指针的函数。解决办法:重写函数和加锁拷贝。
(4)调用线程不安全函数的函数。
一、可重入函数:当它们被多个线程调用时,不会引用任何共享数据。可重入函数是线程安全函数的一个真子集 。
二、关键思想是咱们用一个调用者传递进来的指针取代了静态的next变量。
三、显式可重入:没有指针,没有引用静态或全局变量
隐式可重入:容许它们传递指针
四、可重入性即便调用者也是被调用者的属性,并不仅是被调用者单独的属性。
一、竞争:当一个程序的正确性依赖于一个线程要在另外一个线程到达y点以前到达它的控制流中的x点时,就会发生竞争。
二、线程化的程序必须对任何可行的轨迹线都正确工做。
一、死锁:一组线程被阻塞了,等待一个永远也不会为真的条件。
二、程序员使用P和V操做不当,以致于两个信号量的禁止区域重叠。
三、重叠的禁止区域引发了一组称为死锁区域的状态。
四、死锁是不可预测的。
一、教材:第十二章 二、课程资料:https://www.shiyanlou.com/courses/413 实验楼实验 三、学习指导:http://group.cnblogs.com/topic/73069.html