共享内存并发算法与互斥锁/信号量之间的关系

时间:2012-03-11 16:36:05

标签: concurrency synchronization semaphore shared-memory

我试图弄清楚基于共享内存的并发算法(Peterson's / Bakery)与信号量和互斥量的使用之间的关系。

在第一种情况下,我们有一个没有操作系统干预的系统,进程可以使用共享内存和忙碌等待来自行同步。

在第二种情况下,操作系统为进程/线程提供阻塞功能,而不必忙于等待。

除了信号量之外,我们是否还想使用共享内存(以确保公平/缺乏饥饿),或者操作系统是否提供了更好的方法来实现这一目标?

(我想知道一般概念,但特定于POSIX / Win32 / JAVA线程的答案也很有趣。)

非常感谢!

1 个答案:

答案 0 :(得分:1)

我无法想到你真正想要的任何情况是忙碌的等待。忙碌的等待只消耗处理器时间而没有实现任何目标。这并不是说“忙等待”算法没用(它们是),但“忙等待”部分不是理想的属性,它只是 属性的必然结果。期望的。

彼得森的锁定算法和Lamport的面包店算法基本上只是互斥锁概念的实现。操作系统设施提供相同概念的实现,但具有不同的权衡。

互斥锁的“理想”实现会产生“零开销” - 如果当前没有互斥锁,那么获取互斥锁上的锁将不会花费任何时间,等待线程会在前一个时刻唤醒所有者释放了锁,同时,等待线程不会占用任何处理器时间。

“忙等待”或“自旋锁定”算法交换等待线程使用的处理器时间,以减少唤醒时间。如果线程当前在处理器上进行调度,则忙碌服务器将以处理器可以传输用于获取锁定和同步线程的必要数据的速度唤醒,但是在等待时它将消耗其最大分配处理器时间。如果线程数超过可用处理器的数量,则可能需要花费时间从当前拥有互斥锁的线程开始,从而使等待时间更长。但是,在某些情况下,解锁和锁定之间的低延迟值得权衡。

另一方面,使用OS工具将等待线程置于睡眠状态的“阻塞”互斥锁具有不同的权衡。在这种情况下,解锁互斥锁和获取它的等待线程之间的时间可能非常大,可能比忙等待算法大几百倍。好处是等待线程在等待时确实不消耗处理器时间,因此操作系统可以在线程等待时安排其他工作。因此,这可以潜在地减少总体等待时间,并增加系统的总吞吐量。

一些互斥实现使用忙等待和阻塞的组合:它们忙 - 等待一小段时间,然后如果在短时间内无法获取锁,则切换到阻塞。如果在线程开始等待之后不久释放锁定,则具有快速唤醒的好处,而如果线程必须等待很长时间则不消耗处理器时间。它还具有短处理器的高处理器使用率和长时间等待的慢速唤醒的缺点。