我一直在通过C / C ++阅读Windows一书。在第215页的第8章中,作者比较了各种同步机制的性能。我发现互斥量表现不佳。当4个线程同时运行时,它会花费超过二十三秒来进行互斥锁同步。
为什么Win32互斥锁如此耗时?我们什么时候可以使用互斥锁?
PS:我在GitHub中发布了测试代码:https://gist.github.com/985198
感谢您的回复。
答案 0 :(得分:8)
Win32中的互斥锁是一个内核对象,这意味着每次使用它(Wait
,Release
)都需要进行内核模式并返回用户模式的系统调用。另外,如果您的线程实际上必须等待互斥锁,它会丢失其量程,而另一个可以运行的线程会在CPU上进行调度。在WinXP和更早版本(以及可能是某些更高版本的Windows)上,互斥锁是“公平的”,这意味着如果你的线程最后等待互斥锁,它将是最后一个接收互斥锁,这进一步增加了争用的可能性。 / p>
使用互斥锁的原因是您可以在进程之间轻松共享它们,当拥有它的线程被终止时您可以得到通知,并且您可以使用WaitForMultipleObjects
等待它们与其他对象一起使用。
请注意,您在此基准测试中使用它们不是使用它们的理想方式,因为获取互斥锁的开销远远超过您正在进行的工作量。
答案 1 :(得分:7)
因为互斥锁是内核对象,所以它们上的所有操作都需要上下文切换。这种操作相对昂贵。经验法则是,当您需要在同一进程中的线程之间共享资源时,请使用CRITICAL_SECTION对象。当您需要在不同进程中的线程之间共享资源时,请使用Win32互斥锁。
答案 2 :(得分:1)
CRITICAL_SECTION是一个自旋锁,它在用户空间中旋转以获取锁。如果它在旋转结束时无法获得锁定(受旋转计数限制),则会进入可唤醒等待(WaitForSingleObject())。因此,对于要保护的短代码段(临界区名称来自它),CRITICAL_SECTION是要走的路。如果您计划执行IO和其他耗时的任务,CRITICAL_SECTION与互斥/信号量相比不会给您带来任何节省。