为什么互斥锁不需要一个互斥锁(而那个互斥锁需要一个互斥锁……)

4
我正在通过指针传递一些变量(cv::Mat和bool类型)到几个线程中,并试图理解何时需要使用互斥锁。我发现如果在cv::Mat上不使用互斥锁,我的程序会崩溃(可能是因为一个线程正在写入另一个线程正在读取的内存区域),所以我已经为这些变量实现了互斥锁,问题得到了解决。
但现在,互斥锁是我要通过指针传递给每个线程的另一个变量。所以,在这种情况下,处理互斥锁变量的使用与需要互斥锁的其他变量相同,那么互斥锁有什么特别之处,我为什么不需要一个互斥锁呢(当然,这样做将无休止地进行,概念是行不通的)。
明确一点,我现有的代码运行良好,这更多是为了教育目的。
示例:
//Common frames 
cv::Mat captureimage, displayimage;
std::mutex capturemutex, displaymutex;

//Start image capture thread
std::thread t_imagecapture( CaptureImageThread, &captureimage, &capturemutex, &exitsignal );
//Start image processor thread
std::thread t_imageprocessor( ProcessImageThread, &captureimage, &capturemutex, &exitsignal );
//Start display thread
std::thread t_displayupdate( DisplayUpdateThread, &displayimage, &displaymutex, &exitsignal );

3
通常情况下,只需要一个互斥锁即可控制线程之间共享的所有变量。 - πάντα ῥεῖ
1
互斥锁是自身设计为线程安全的。它们使用操作系统的底层机制,保证在锁定/解锁互斥锁时不会出现竞态条件。 - Hayt
3
我已经为这些变量实现了互斥锁。-- 不,你并没有“实现”互斥锁;你已经“使用”了互斥锁。 - Pete Becker
关于为每个变量使用唯一的互斥锁与使用公共互斥锁,是否使用多个互斥锁会有性能提升?例如,在这个应用程序中,我不希望t_displayupdate线程在t_imagecapture线程正在写入捕获图像时等待读取displayiamge。 - DrTarr
如果这些互斥量保护的数据结构具有完全不相关的处理,那么您可以获得一些性能提升。否则,如果您需要同时获取两个或更多的互斥量,您很容易会出现死锁问题,请参见https://en.wikipedia.org/wiki/Deadlock。 - Serge
1个回答

5

互斥锁是一种原子锁。它使用低级方法(CPU),例如可以无法中断地执行测试和设置来锁定,因此不需要外部锁来执行此操作。一旦锁定设置好了,其他线程就不能这样做,因此互斥锁可以保护对其他资源的访问。


是的,我并没有想到需要指出所有的实现。我甚至不知道所有的实现,所以我会编辑一下来强调这一点。 - stefaanv
谢谢!此外,这个网站对于解释原子操作非常有帮助:http://preshing.com/20130618/atomic-vs-non-atomic-operations/。而在原子操作的主题上,阅读此线程:https://dev59.com/3Gox5IYBdhLWcg3wcj54 使我听起来需要使用std::atomic来处理我的布尔变量。 - DrTarr
是的,atd::atomic在多线程工作时是一个改变游戏规则的东西。当需要原子地执行更多代码或保护更复杂的资源时,仍然需要使用互斥锁。 - stefaanv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接