【问题标题】:Stop thread from re-acquiring mutex after releasing it释放线程后停止线程重新获取互斥锁
【发布时间】:2021-01-29 22:51:30
【问题描述】:

我正在制作自己的互斥锁来同步我的线程,但我遇到了以下问题:

  • 同一线程似乎在释放互斥锁后立即重新获取它

我尝试过的:

  • 告诉它让执行给另一个线程(SwitchToThread、Sleep、YieldProcessor)
  • 增加循环之间的延迟(最多 1 秒)

这是它的工作原理:

我有一个带有状态值的结构:

volatile unsigned int state;

当我想获取互斥体时,我会检查状态直到它被释放(打开),然后获取(关闭)它并跳出无限循环并做任何需要做的事情:

    unsigned int previous = 0;

    for (;;)
    {
        previous = InterlockedExchangeAdd(&mtx->state,
                                          0);
        if (STATE_OPEN == previous)
        {
            InterlockedExchange(&mtx->state,
                                STATE_CLOSED);

            break;
        }

        Sleep(delay);
    }

然后我简单地释放它以供下一个线程获取它:

InterlockedExchange(&mtx->state,
                    STATE_OPEN);

我使用它的方式是,我只是有一个全局易失整数,我在一个线程中加 1,在另一个线程中减 1。增加延迟有助于使该数字不会变得非常低或非常高并陷入仅在单个线程中执行的循环中,但是 1 秒以上的延迟不适用于我的其他目的.

我怎样才能确保所有线程都有机会获取互斥锁而不是卡在单个线程中?

【问题讨论】:

  • "...这使得 volatile 对象适合与信号处理程序通信,但不适用于另一个执行线程..." @ 987654321@
  • 但是伙计,来自 WINAPI(用于线程同步)的互锁函数在原型中指定了 volatile。据我所知,它的目的是告诉编译器在尝试优化代码时不要删除它或以任何其他方式弄乱它。
  • @RichardCritten:这是针对 ISO C++ 的。但是,上面的代码使用了非标准的InterlockedExchangeAdd,它需要volatile。线程安全不是来自volatile,而是来自记录在案的行为:“这个函数相对于对其他互锁函数的调用是原子的。”。这是相当有限的,但上面的代码始终使用互锁函数。
  • 你使用的是c还是c++?请不要同时标记两者
  • 我使用的是 C,但为什么在我只是调用相同的 WINAPI 函数的情况下这很重要?

标签: c++ c multithreading winapi mutex


【解决方案1】:

互斥锁完全按照它应该做的:它防止多个线程同时运行。

要阻止线程重新获取互斥锁,基本的解决方案是不访问受互斥锁保护的共享资源。该线程可能应该在做其他事情。

您也可能遇到设计问题。如果您有多个资源受单个互斥锁保护,则线程之间可能存在错误争用。如果每个资源都有自己的互斥锁,则多个线程可以各自在自己的资源上工作。

【讨论】:

    猜你喜欢
    • 2021-02-19
    • 2013-01-31
    • 1970-01-01
    • 1970-01-01
    • 2014-11-24
    • 2015-03-21
    • 1970-01-01
    • 2014-05-02
    • 2012-12-25
    相关资源
    最近更新 更多