使用互斥锁作为信号量?

发布于 2024-11-25 22:00:27 字数 1028 浏览 1 评论 0原文

我需要两个线程以“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 变量、互斥体和条件变量)。为了简洁起见,我省略了实现,但它确实很简单。

互斥解决方案好吗?或者其中有什么微妙的错误吗?

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

I need two threads to progress in a "tick tock" pattern. When implmented with a semaphore this looks fine:

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 );
   }
}

However, if I do the same thing with a mutex ( which is technically a binary semaphore ), it has an odd code smell.

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();
   }
}

I think the smell is that a mutex isn't meant to convey information to another thread. (The c++11 standard committee added a spurious fail to try_lock to defeat unexpected information transfer; §30.4.1/14.) It seems like mutexes are meant to synchronize access to a variable, which can then convey information to another thread.

Lastly, when implemented with a std::condition_variable, it looks correct but it's more complicated ( a tick_vs_tock variable, a mutex, and a condition variable). I've omitted the implementation for brevity, but it's really straight forward.

Is the mutex solution fine? Or is there something subtly wrong with it?

Is there a good pattern for solving my tick/tock problem that I haven't thought of?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

佞臣 2024-12-02 22:00:27

互斥体不仅仅是一个二进制信号量,它还有一个限制,即只有锁定线程才可以解锁它。

你违反了这条规则。

编辑:

来自MSDN

如果调用线程不拥有该对象,则 ReleaseMutex 函数将失败
互斥对象。

从 Google 发现的 pthread_mutex_unlock 的某个网站:

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

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

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

A Mutex is not simply just a binary semaphore, it also has the limitation that only the locking thread is allowed to unlock it.

You are breaking that rule.

Edit:

From MSDN:

The ReleaseMutex function fails if the calling thread does not own the
mutex object.

From some site that google turned up for pthread_mutex_unlock:

The pthread_mutex_unlock() function may fail if:

EPERM The current thread does not own the mutex.

And you will find the same on other mutex implementations. It makes sense because a mutex is supposed to guard a thread's access to a resource, so another thread should not be able to unlock it.

暗地喜欢 2024-12-02 22:00:27

由于您有使用信号量的情况,我认为解决方法是可移植 使用互斥体和条件变量实现一个

这可能不是特别有效(因为它将为每个信号量使用互斥体/条件变量对),但您可以在拥有自己的信号量的系统(例如 Posix 和 Windows)上切换替代实现。

显然 信号量“太容易出错” ”。尽管对 Boost 抱有应有的尊重,但我认为至少我们中的一些人可以做到这一点。当然,您可能会陷入困境尝试使用多个信号量完成复杂的事情,它们是一个相当低级的工具。但当它们是正确的时候,就没问题了。

Since you have a case to use a semaphore, I think the fix is to portably implement one using a mutex and a condition variable.

This might not be especially efficient (since it'll use a mutex/condvar pair per semaphore), but you can switch in an alternate implementation on systems that have their own semaphores (such as Posix and Windows).

Apparently semaphores are "too error-prone". With all due respect to Boost, I think at least some of us can manage. Certainly you can tie yourself in knots trying to do complicated things with multiple semaphores, and they are a pretty low-level tool. But when they're the right thing, no problem.

旧故 2024-12-02 22:00:27

嗯,你明白 Mutex 的全部意义了吗?
释放一个互斥体并锁定另一个互斥体显然是不明智的。

Hm, have you understood the whole point of the Mutex?
It's clearly unwise to release one mutex and lock the other.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文