基本概念
主要任务
对多个相关进程在执行次序上进行协调,使并发执行的诸进程之间能按照一定的规则(或时序)共享系统资源,并能很好地相互合作,从而使程序的执行具有可再现性。
两种形式的制约关系
1) 间接相互制约关系(譬如:进程间共享系统的互斥硬件资源)
2) 直接相互制约关系(譬如:合作完成一个任务,共享同一个缓冲区的数据)
临界资源(Critical Resouce)
临界资源是一次仅允许一个进程使用的共享资源。各进程采取互斥的方式,实现共享的资源称作临界资源。属于临界资源的硬件有,打印机,磁带机等;软件有消息队列,变量,数组,缓冲区等。诸进程间采取互斥方式,实现对这种资源的共享。
临界区(critical section)
不论是硬件临界资源还是软件临界资源,多个进程必须互斥地对它进行访问。人们把在每个进程中访问临界资源的那段代码称为临界区(critical section)。
一次只允许一个进程进入的该进程的那一段代码!
1. while(true) 2. { 3. 进入区(检查欲访问的临界资源标志,置为访问中) 4. 临界区(访问临界资源) 5. 退出区(修改临界资源的访问标志,置为未被访问) 6. 剩余区 7. }
同步机制应遵循的规则
为实现进程互斥地进入自己的临界区,可用软件方法,更多的是在系统中设置专门的同步机构来协
调各进程间的运行。所有同步机制都应遵循下述四条准则:
(1) 空闲让进。(若干进程要求进入空闲临界区时,若资源空闲, 应尽快使一进程进入临界区)
(2) 忙则等待。
(3) 有限等待。(从进程发出进入请求到允许进入,不能无限等待)
(4) 让权等待。(若不能进入自己的临界区,应立即释放cpu,以免进程陷入“忙等”)
硬件同步机制
关中断
关中断是实现互斥的最简单的方法之一。在进入锁测试之前关闭中断,直到完成锁测试并上锁之后才能打开中断。这样,进程在临界区执行期间,计算机系统不响应中断,从而不会引发调度,也就不会发生进程或线程切换。由此,保证了对锁的测试和关锁操作的连续性和完整性,有效地保证了互斥。
关中断的方法存在许多缺点:
① 滥用关中断权力可能导致严重后果;
② 关中断时间过长,会影响系统效率,限制了处理器交叉执行程序的能力;
③ 关中断方法也不适用于多CPU 系统,因为在一个处理器上关中断并不能防止进程在其它处理器上执行相同的临界段代码。
利用Test-and-Set实现互斥
这是一种借助一条硬件指令—“测试并建立”指令TS(Test-and-Set)以实现互斥的方法。在许多计算机中都提供了这种指令。可以看作是一个函数过程(原子操作)。
1. boolean TestAndSet(boolean &lock) 2. { 3. boolean rv = lock; 4. lock = true; 5. return rv; 6. }
1. while(TestAndSet(&lock)) ; 2. 临界区 3. lock = false; //退出区 4. 剩余区
每个临界资源设置一个布尔变量lock,由于变量lock代表了该资源的状态,故可以将它看成一把锁。lock的初值为false,表示临界值资源空闲
利用Swap指令实现互斥
该指令称为对换指令,在Intel 80x86中又称为XCHG指令,用于交换两个字的内容。
1. void swap(boolean &lock, boolean &key) 2. { 3. boolean tmp = lock; 4. lock = key; 5. key = tmp; 6. }
每个临界资源设置一个全局的布尔变量lock,初值为false,在每个进程中再利用一个局部变量key
适用于单处理器或共享主存的多处理器。但当临界资源忙碌时,其他访问进程必须不断的进行测试,处于一种“忙等”状态,不符合“让权等待”原则。难于用于解决复杂的进程同步问题。
解决“忙等”的一个方案:添加 WaitQueue,等待队列。当进入while忙等时,把TCB加入等待队列,让出CPU。当运行中的线程退出后,Release设置value=0,从等待队列获取一个线程,唤醒他。但 这里会发生上下文切换。如果临界区很长,远远大于上下文切换的开销,那么采取
WaitQueue更合理。
信号量机制
整型信号量
最初由Dijkstra把整型信号量定义为一个用于表示资源数目的整型量S,它与一般整型量不同,除初始化外,仅能通过两个标准的原子操作(Atomic Operation) wait(S)和signal(S)来访问。很长时间以来,这两个操作一直被分别称为P、V操作。
1. wait(S){ 2. while(S <=0); 3. S--; 4. }
1. signal(S){ 2. S++; 3. }