【问题标题】:Use a mutex as a semaphore?使用互斥锁作为信号量?
【发布时间】:2011-10-11 20:30:32
【问题描述】:

我需要两个线程以 “tick tock” 模式进行。当使用信号量实现时,这看起来很好:

Semaphore tick_sem(1);
Semaphore tock_sem(0);

void ticker( void )
{
   while( true )
   {
      P( tick_sem );
      do_tick();
      V( tock_sem );
   }
}

void tocker( void )
{
   while( true )
   {
      P( tock_sem );
      do_tock();
      V( tick_sem );
   }
}

但是,如果我对互斥体(从技术上讲是二进制信号量)做同样的事情,它会有一种奇怪的代码气味。

std::mutex tick_mutex;
std::mutex tock_mutex;
tock_mutex.lock();

void ticker( void )
{
   while( true )
   {
      tick_mutex.lock();
      do_tick();
      tock_mutex.unlock();
   }
}

void tocker( void )
{
   while( true )
   {
      tock_mutex.lock()
      do_tock();
      tick_mutex.unlock();
   }
}

我认为这种气味是互斥体并不意味着将信息传达给另一个线程。 (c++11 标准委员会在 try_lock 中添加了一个虚假的失败,以阻止意外的信息传输;§30.4.1/14。)似乎互斥锁旨在同步对变量的访问,然后可以将信息传递给另一个线程。

最后,当使用std::condition_variable 实现时,它看起来正确但更复杂(tick_vs_tock 变量、互斥体和条件变量)。为简洁起见,我省略了实现,但它真的很简单。

互斥体解决方案好吗?还是有什么微妙的问题?

有没有一个很好的模式来解决我没有想到的滴答/滴答问题?

【问题讨论】:

  • 顺便说一句:这个问题的出现只是因为 C++0x 没有 std::semaphore 并且双 std::mutex 解决方案没有 std::condition_variable 解决方案复杂。
  • (为什么)unlock() 线程中的互斥锁是否有效?
  • @Steve 这是一个非常好的问题(提示、提示、轻推、轻推)。

标签: c++ concurrency c++11 mutex semaphore


【解决方案1】:

互斥量不仅仅是一个二进制信号量,它还有一个限制,就是只允许锁定线程解锁它。

你违反了这条规则。

编辑:

来自MSDN

如果调用线程不拥有 互斥对象。

来自谷歌为pthread_mutex_unlock找到的某个网站:

如果出现以下情况,pthread_mutex_unlock() 函数可能会失败:

EPERM 当前线程不拥有互斥锁。

您会在其他互斥体实现中发现相同的情况。这是有道理的,因为互斥锁应该保护线程对资源的访问,所以另一个线程不应该能够解锁它。

【讨论】:

  • 根据史蒂夫的评论。这真的是规则吗?这绝对是个好主意。
  • @deft - 我认为这取决于互斥锁的实现,这取决于系统。解锁别人的互斥锁通常不是一个好主意,即使系统允许这样做。
  • @deft_code:我还没有阅读 FDIS 的 mutex 部分,但如果它不是规则,我会感到惊讶。互斥锁有一个所有者,这是它们作为同步工具的基本定义的一部分。
  • 我们在这里,30.1.4.2/22:“要求:调用线程应拥有互斥锁”。所以 UB 如果没有。
【解决方案2】:

由于您有使用信号量的案例,我认为解决方法是可移植到 implement one using a mutex and a condition variable

这可能不是特别有效(因为它会为每个信号量使用一个 mutex/condvar 对),但您可以在具有自己的信号量的系统(例如 Posix 和 Windows)上切换替代实现。

显然是semaphores are "too error-prone"。尽管对 Boost 给予了应有的尊重,但我认为至少我们中的一些人可以做到。当然,您可以将自己打结trying to do complicated things with multiple semaphores,它们是一个相当低级的工具。但是当它们是正确的时候,没问题。

【讨论】:

  • 我同意“太容易出错”的事情很奇怪。互斥锁也容易出错。锤子也可以。
猜你喜欢
  • 1970-01-01
  • 2012-05-07
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 2016-08-30
  • 2017-08-24
  • 2011-01-20
相关资源
最近更新 更多