条件变量虚假唤醒/循环任务

时间:2018-12-21 04:00:46

标签: c++ multithreading c++17 round-robin

我是C ++线程的新手,我正在尝试使用C ++线程编写循环(合作)任务管理器。下面的round_robin_task_ulock声明是否有效-这是一个全局静态变量。我想将互斥锁的锁定推迟到任务管理器线程开始运行之前。

static std::mutex                      round_robin_task_mutex;
static std::condition_variable         task_manager_cvar; 
static thread                          round_robin_task_manager_thread;
static std::unique_lock<std::mutex>    
     round_robin_task_ulock(round_robin_task_mutex, std::defer_lock);

static void round_robin_task_manager()
{
    round_robin_task_ulock.lock();
    //..
}

任务管理器线程一旦运行,便可以启动循环任务,并先执行通知,然后再等待

 round_robin_tasks[current_task_id].task_cvar.notify_one();
 // release the mutex and go to sleep
 task_manager_cvar.wait(round_robin_task_ulock); 
 // now we own the mutex again

,当循环任务想要暂停自身时,它会通知任务管理器线程

 task_manager_cvar.notify_one();
 round_robin_tasks[current_task_id].task_cvar.wait
                  (round_robin_task_ulock, [] { return  
                      round_robin_tasks[my_task_id].task_running_now; } );

这个有明显的问题吗?我读过有关虚假唤醒的信息。在循环任务仍拥有互斥锁的情况下,是否有可能通过虚假唤醒唤醒任务管理器线程,还是可以保证当wait函数返回时,互斥锁始终由调用wait的线程拥有(锁定)。 / p>

1 个答案:

答案 0 :(得分:1)

您应该构建代码,以便在没有任何条件变量的情况下它仍然可以工作。如果它在锁定互斥锁,检查条件,解锁互斥锁并立即重复循环的情况下能够工作,则它将与条件变量一起使用,效率只会更高。

一个实现可以每10毫秒唤醒您的条件变量,如果它出于某种原因而想要,或者与诸如MWAIT,高速缓存行和事务性锁之类的指令发生某种怪异的交互,或者硬件功能。

我似乎回想起有关一种体系结构的信息,该体系结构在每当写入高速缓存行的任何部分时都会在内存位置发出等待事件的信号。而且线程库没有为缓存行大小填充足够的结构。

因此,您可能必须每秒处理数百次唤醒,并且代码仍应正常工作。

从我对您所写内容的了解来看,您只有一个地方要检查谓词,这是经过条件必须为真的条件。并且在每次通知之前,您都应该更新谓词。谓词必须始终在条件变量使用的同一锁保护下进行写入或读取。

如果您想要其他行为,则可以使用信号量