其他线程正在等待时如何阻塞线程

时间:2019-01-07 10:30:21

标签: c++ multithreading

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

这里是:

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

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

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

我愿意接受任何想法!

1 个答案:

答案 0 :(得分:0)

好的,所以我终于有机会关闭它。我尝试了此处和链接中提出的一些解决方案。 最后,我将用于执行命令的互斥锁与等待同步调用的计数器结合在一起(该计数器当然也受互斥锁保护)。 异步线程在尝试获取互斥之前先检查计数器,然后等待计数器为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();
    }
}