1.1 进程同步机制
(1) 原子操作:所谓原子操作,就是该操作绝不会在执行完毕前被任何其他任务或事件打断,也就说,它是最小的执行单位,不可能有比它更小的执行单位。原子操作需要硬件的支持,因此是架构相关的。
(2) 信号量:信号量sem是一整数,当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。注意,信号量的值仅能由PV操作来改变。
P(S):(1)将信号量S的值减1,即S=S-1 (2)如果S>=0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。
V(S):(1)将信号量S的值加1,即S=S+1;(2)如果S>0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。
(3) 自旋锁:自旋锁最多只能被一个内核任务持有,如果一个内核任务试图请求一个已经被持有的自旋锁,那么这个任务就会一直循环——旋转——等待锁重新可用。自旋锁在内核中主要用来防止多处理器中并发访问临界区,防止内核抢占造成的竞争。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。
(4) 管程:将共享资源的数据结构以及对共享变量能够进行的所有操作集中在一个模块中。每次只允许一个进程访问管程内资源。管程内部有进程等待队列,以及等待和唤醒操作,队列称之为条件队列。当进入管程的进程因资源被占用等原因不能继续运行时,进程进入条件队列,并释放管程互斥权。当管程的另一进程释放与某条件变量相关的资源时,唤醒在该条件上等待的一个进程。
(5) 会合:一个进程可以有许多入口,一个入口对应一段程序,一个进程可以调用另一个进程的入口。当一个进程调用另一个进程的入口,而且被调用的进程已准备好接受这个调用时,会合就发生了。当调用者发出调用请求时,被调用的进程未准备接受这个调用时,则调用者等待;反之,当被调用者准备接受调用,而当前尚无调用者时,则被调用者等待。即先到达会合处等待后到达者。当多个进程调用同一个进程的同一个入口时,被调用者按先来先服务(FCFS)的次序接受调用。入口处可以携带调用参数,还可以有返回参数,以实现信息的交换。被调用者可以选择会合的入口。
(6) 分布式系统
1.2 线程同步机制
(1) 事件(Event):一个事件有两种状态:激发状态和未激发状态。也称有信号状态和无信号状态。事件又分两种类型:手动重置事件和自动重置事件。手动重置事件被设置为激发状态后,会唤醒所有等待的线程,而且一直保持为激发状态,直到程序重新把它设置为未激发状态。自动重置事件被设置为激发状态后,会唤醒“一个”等待中的线程,然后自动恢复为未激发状态。
(2) 临界区(Critical Section):通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。
(3) 互斥器(Mutex):采用互斥对象机制。 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享。
(4) 信号量(Semaphore):它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。