【问题标题】:Why doesn't a mutex need a mutex (and that mutex need a mutex...)为什么互斥锁不需要互斥锁(而互斥锁需要互斥锁......)
【发布时间】:2016-09-02 11:45:48
【问题描述】:

我通过指针(cv::Mat's 和 bool's)将几个变量传递给多个线程,并试图了解何时需要使用互斥锁。我发现如果不在 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 );

【问题讨论】:

  • 通常线程间共享的所有变量使用一个互斥体就足够了。
  • 互斥锁本身被设计为线程安全的。它们使用操作系统的底层机制,保证在锁定/解锁互斥锁时不会出现竞争条件。
  • “我已经为这些变量实现了互斥锁”——不,你还没有实现互斥锁;你已经使用过互斥体。
  • 关于为每个变量使用唯一互斥锁与使用普通互斥锁相比,使用多个互斥锁不会提高性能吗?例如,在这个应用程序中,我不希望 t_displayupdate 线程在 t_imagecapture 线程正在写入捕获图像时等待读取 displayiamge。
  • 如果受这些互斥锁保护的数据结构具有完全不相关的处理,您可以获得一些性能提升。否则,如果您需要一次获取两个或多个互斥锁,很容易陷入死锁,请参阅en.wikipedia.org/wiki/Deadlock

标签: c++ multithreading opencv mutex


【解决方案1】:

互斥锁是一种原子锁。它使用低级方法(CPU),例如,它可以test-and-set 锁而不会被中断,因此它不需要外部锁来执行此操作。并且一旦设置了锁,其他线程就无法做到这一点,因此互斥锁可以保护其他资源的访问。

【讨论】:

  • 是的,我认为我不需要指出所有的实现。我什至不知道所有的实现,所以我将对其进行编辑以突出显示。
  • 谢谢!此外,this 站点有助于解释原子操作。而原子操作的主题,阅读this thread 听起来我需要为我的布尔变量使用std::atomic。
  • 是的,atd::atomic 在多线程工作时改变了游戏规则。当需要以原子方式完成更多代码或必须保护更复杂的资源时,仍然需要互斥锁。