【问题标题】:How to block a thread while other threads are waiting如何在其他线程等待时阻塞线程
【发布时间】:2019-01-07 10:30:21
【问题描述】:

我有一个非常具体的问题要解决。我很确定世界上其他人已经遇到并解决了它,但我还没有找到任何解决方案。

这里是:

  • 我有一个线程从队列中弹出命令并异步执行它们
  • 我可以从任何其他线程调用函数来同步执行命令,绕过队列机制,返回结果,并优先执行(在当前执行结束后)。
  • 我有一个互斥锁来保护命令执行,因此一次只执行一个命令 问题是,对于一个简单的互斥锁,我无法确定同步调用在发生冲突时会在异步线程之前获得互斥锁。事实上,我们的测试表明分配非常不公平,异步线程总是获胜。

所以我想在有同步调用等待时阻塞异步线程。我事先不知道可以进行多少次同步调用,并且我不控制进行调用的线程(因此任何使用线程池的解决方案都是不可能的)。

我正在使用 C++ 和 Microsoft 库。我知道基本的同步对象,但也许有更高级的对象或方法适合我不知道的问题。

我愿意接受任何想法!

【问题讨论】:

  • 您能以minimal reproducible example 的形式向我们展示您目前的方法吗?
  • [...]and taking priority of execution[...] 您如何将同步线程优先于异步线程?一个好的优先级应该做到这一点。 stackoverflow.com/questions/11666610/…
  • So I want to block the asynchronous thread while there is a synchronous call waiting. - 那你为什么不呢?这可以像检查 are there any sync calls pending 一样简单,在异步循环的顶部,然后什么都不做(不要获取互斥锁)(如果有的话)。
  • 谢谢!实际上,我认为我需要的只是链接 user1810087 发布的内容。如果可行,我会看看并设置解决。
  • 一种简单的方法是添加另一个互斥锁。同步线程持有它它锁定原来的互斥锁;异步线程在之前短暂地接受它。

标签: c++ multithreading


【解决方案1】:

好的,我终于有机会关闭它了。我尝试了这里和发布的链接中提出的一些解决方案。 最后,我结合了一个用于命令执行的互斥锁和一个等待同步调用的计数器(当然,该计数器也受到互斥锁的保护)。 异步线程在尝试获取互斥体之前检查计数器,并等待计数器为 0。此外,为了避免睡眠循环,我添加了一个在计数器设置为 0 时设置的事件。异步线程等待此事件在尝试获取互斥锁之前。

void incrementSyncCounter()
{
    DLGuardThread guard(_counterMutex);
    _synchCount++;
}

void decrementSyncCounter()
{
    DLGuardThread guard(_counterMutex);
    _synchCount--;

    // If the counter is 0, it means that no other sync call is waiting, so we notify the main thread by setting the event
    if(_synchCount == 0)
    {
        _counterEvent.set();
    }
}

unsigned long getSyncCounter()
{
    DLGuardThread guard(_counterMutex);
    return _synchCount;
}

bool executeCommand(Command* command)
{
    // Increment the sync call counter so the main thread can be locked while at least one sync call is waiting
    incrementSyncCounter();

    // Execute the command using mutex protection
    DLGuardThread guard(_theCommandMutex);
    bool res = command->execute();
    guard.release();

    // Decrement the sync call counter so the main thread can be unlocked if there is no sync call waiting
    decrementSyncCounter();

    return res;
}

void main ()
{
    [...]
    // Infinite loop
    while(!_bStop)
    {
        // While the Synchronous call counter is not 0, this main thread is locked to give priority to the sync calls.
        // _counterEvent will be set when the counter is decremented to 0, then this thread will check the value once again to be sure no other call has arrived inbetween.
        while(getSyncCounter() > 0)
        {
            ::WaitForSingleObject (_counterEvent.hEvent(), INFINITE);
        }

        // Take mutex
        DLGuardThread guard(_theCommandMutex);

        status = command->execute();

        // Release mutex
        guard.release();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-16
    • 2019-06-14
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多