1. 注意点
1. 为什么协程的运行次序会导致出错?在什么共享的资源上出现的错误?
2. 操作系统如何实现原子操作的?
3. 同步和互斥的区别,同步(协调进程执行次序,数据一致性);互斥(进程互斥访问临界资源);互斥和同步可抽象为:都是协调进程代码执行次序。
4. 整型信号量-->记录信号量-->管程。逐步引入。
2. 进程并发时协同进程面临的问题
在进程并按时,各个协程运行次序的不同导致不同的运行结果,从而导致运行出错。(运行结果数据不一致性问题)
3. 数据不一致问题
1. 在现场操作系统中,每个进程可在任何时候被中断,仅仅进程的部分代码可以连续执行。
2. 共享数据并发/并行访问:会出现数据不一致性问题。又称为不可再现性:同一个进程在同一数据上多次运行的结果不一样。
3. 解决访问:同步(互斥)机制。
4. 原子操作
原子操作:一个操作在整个执行期间不能中断。
5. 数据不一致性的原因
进程间存在竞争条件,即多个进程并发访问同一共享数据,而共享数据的最终结果取决于最后操作的的进程。
同步和互斥机制
1. 防止竞争条件
2. 同步的含义:协调进程的执行次序,使并发进程间能有效的共享数据和相互合作,保证数据一致性。
3. 互斥的含义:进程排他性的运行某段代码,任何时候只能一个进程运行。互斥访问独占资源。(也算是协调代码的执行次序,互斥也是一种特殊的同步)
3. 临界区
临界资源:一次只允许一个进程使用的资源。也称为:互斥资源、独占资源或共享变量。 (一次怎么理解?)
共享资源:一次允许多个进程使用的资源。(一次怎么理解?)
临界区:是进程内代码片段,每个进程有一个或多个临界区,临界区的设置方法由程序员确定。如能保证各个进程互斥进入具有相同临界资源的临界区,可以实现对临界资源的互斥访问。(临界区与临界资源对应)
4. 临界区使用准则
1. 互斥准则:假如一个进程在临界区执行,其他进程应排斥在该临界区外。有相同临界资源的临界区才需要互斥,没有相同临界资源的临界区不需要互斥。(从这也可以看出,是协调进程执行的次序,也是符合同步的定义,所以互斥也是一种同步)
2. 有空让进准则:当临界区无进程执行时,不能无限期延长下一个要进入临界区进程的等待时间。(可以理解为,进程出临界区后要释放锁)
3. 有限等待准则:每个进程进入临界区前的等待时间必须有限,不能无限。(比如临界代码要尽可能小)
5. 访问临界区的方法
进入区-->临界区-->退出区-->其他区
进入区:实现互斥准则
退出区:实现有空让进准则
6. 信号量
1. 信号量同步和互斥的一种实现方法。
2. 保证两个或多个代码段不能同时被调用执行。
3. 进入代码段运行前,进程必须获得一个信号量。(进入区)
3. 执行关键代码段后,进程必须释放信号量。(退出区)
4. 信号量有值,为正说明空闲,为负说明忙碌。
5. 整型信号量,大于表示可以获得信号量;小于等于0表示无法获得信号量。
7. P V操作
1. 两个不可分割的“原子操作”,用来访问信号量。
2. wait--P操作;signal--V操作。
3. 进程调用wait(s)表示要获得一个信号量。s>0 进程获得一个s信号量,继续运行;如s<=0 进程无法获得一个s信号量,进程无法继续运行下去。
4. 整型信号量问题,是忙等。wait的实现是while循环,没有获得一个信号量,会一直循环执行while语句。
8. 记录型信号量
1. 解决整型信号量忙等的问题。
2. 记录型信号量相比整型信号量增加了一个队列,当进程无法获得一个信号量时,马上释放cpu,并把自己转换为等待状态,加入该信号量的等待队列。
3. 与整型信号量的区别:记录型信号量先减一再判断,整型信号量先判断再减一。这样的好处是可以记录由于申请该信号量而阻塞的进程。当S(记录型信号量)为负时,|S|表示等待该信号量的进程数。
4. 记录型信号量添加了阻塞和唤醒机制,消除了忙等。
9. 信号量的两种类型(计数信号量和二值信号量)
1. 计数信号量:是没有限制的整数值,也称为同步信号量。
2. 变化范围就是0和1,也称为互斥信号量。
10. 信号量S的使用
1. S必须且只能赋一次初值。
2. S初值不能为负数。(一开始为负值,就不能进入临界区了)
3. 除了初始化,只能通过P、V操作访问信号量S。
11. 互斥信号量使用方式
1. Semaphore *S //初始化为1
2. wait(S);//P 操作 获取信号量
3. CriticalSection();//临界区代码
4. signal(S);//V 操作
12. 同步信号量的使用
使用情况不同,P、V操作一般在不同的进程。
生产者消费者问题、读者写者问题、银行家就餐问题
13. 管程--(1)信号量机制的优点和缺点
优点:程序效率高,编程灵活。
缺点:需要程序员实现,编程困难;维护也困难,容易出错。
引用管程解决这样的问题。(主要由编程语言解决同步互斥的问题)
14. 管程--(2)
1. 概念:一个管程定义了一个数据结构和能为并发进程所执行(在该数据结构上)的一组操作,这组操作能同步进程和改变管程中的数据。(一个数据结构+操作)
2. 管程实现互斥:管程中的变量只能被管程的操作访问;任何时候只有一个进程在管程中操作。这样的管程类似与临界区。一般由编译器完成。
3. 管程实现同步:引入条件变量和阻塞唤醒操作。如:x是条件变量,x.wait()会使进程阻塞,直到另一个进程调用x.signal()。x.signal()可以唤醒另一个进程。类型与记录信号量。(因获取不到条件变量阻塞的进程,会放在队列中)
4. 管程队列:入口队列、紧急队列、条件队列
15. linux同步机制
1. 禁止使用中断来实现短的临界区
2. 自旋锁:调用wait()不会引起阻塞。(线程空转循环等待锁释放,多用于多处理器)。或者,因为很多内核资源只锁1毫秒的时间片段;所以说,等待自旋锁的释放不会消耗太多CPU的时间
3. 互斥锁:与自旋锁的区别,线程获取不到锁,会阻塞。
4. 条件变量
5. 信号量