C++ C++;11条件变量同步问题

C++ C++;11条件变量同步问题,c++,c++11,sync,stdthread,C++,C++11,Sync,Stdthread,我有一个简单的线程池,它需要能够等待其工作线程使用队列中的所有任务,而无需使用标准的thread::join(),因为我不想杀死线程本身,而只是等待它们在执行循环中完成所有任务。我想用条件变量s来实现这一点,如下所示: ThreadPool.cpp void ThreadPool::addTask(ThreadTaskFunction task, void *arg) { std::lock_guard<std::mutex> t_lock(task_lock); t

我有一个简单的线程池,它需要能够等待其工作线程使用队列中的所有任务,而无需使用标准的
thread::join()
,因为我不想杀死线程本身,而只是等待它们在执行循环中完成所有任务。我想用
条件变量
s来实现这一点,如下所示:

ThreadPool.cpp

void ThreadPool::addTask(ThreadTaskFunction task, void *arg) {
    std::lock_guard<std::mutex> t_lock(task_lock);
    tasks.push_back(ThreadTask(task, arg));

    // For every tasks that is added, I increment a counter
    assignedTasks++;
}

void ThreadPool::join() {
    std::unique_lock<std::mutex> lock(join_lock);
    joinCondition.wait(lock, [this](){
        return assignedTasks == 0;
    });
}
void ThreadPool::addTask(ThreadTaskFunction任务,void*arg){
std::锁紧装置(任务锁);
tasks.push_back(ThreadTask(task,arg));
//对于添加的每个任务,我都增加一个计数器
赋值任务++;
}
void ThreadPool::join(){
std::唯一锁定(连接锁定);
joinCondition.wait(锁定,[此](){
返回assignedTasks==0;
});
}
线程.cpp 请注意,这是ThreadPool的朋友类

void Thread::threadLoop() {
    while (!shouldDie) {
        ThreadTask task;

        if (pool.hasTasks()) {
            {
                std::lock_guard<std::mutex> lock(pool.task_lock);

                if (!pool.hasTasks()) continue;

                task = pool.getTask();
            }

            task.function(task.argument);
            this->completeTask();
        }
    }

    this->isThreadFinished = true;
}

void Thread::completeTask() {
    std::lock_guard<std::mutex> guard(pool.task_lock);

    // When a task is completed, I decrement the counter and notify the main thread that a task has completed.
    pool.assignedTasks--;    
    pool.joinCondition.notify_one();
}
void Thread::threadLoop(){
而(!应该死){
线程任务;
if(pool.hasTasks()){
{
std::锁\保护锁(池.任务\锁);
如果(!pool.hasTasks())继续;
task=pool.getTask();
}
task.function(task.argument);
这->完成任务();
}
}
此->isThreadFinished=true;
}
无效线程::completeTask(){
std::锁定保护(池任务锁定);
//当任务完成时,我减少计数器并通知主线程任务已完成。
pool.assignedTasks--;
pool.joinCondition.notify_one();
}
我用这个东西进行物理模拟,模拟的每一步都会发生这种事情(大约每16毫秒一次)。发生的情况是,经过几百个步骤后,一切都停止了,因为在主线程进入等待状态之前,以某种方式发送了一个通知信号,可能是因为它正在检查状态。如果我进行调试,我可以看到计数器上只剩下一个任务,线程上没有任务运行,队列中没有任务,实际上什么都没有发生。有时,甚至更奇怪的是,只要我用断点暂停执行并重新启动它,一切都会解锁。我试着把更多的锁放在适当的地方,但没有用。 有什么明显的东西我遗漏了吗


更新通过将
assignedtask
变量设置为
volatile
似乎可以解决问题。它经常被修改,有时寄存器中的值没有更新,一切都停止了。以前从来没有这样做过。嗯。:)

您在不同的时间使用两个不同的互斥锁(
join\u lock
pool.task\u lock
)来“保护”
分配的任务
,这是一个简单的老式竞争条件。

您使用两个不同的互斥锁(
join\u lock
pool.task\u lock
)来“保护”
assignedtask
在不同的时间-这是一个简单的老式竞争条件。

join不会杀死线程,它会等待它们完成,但我不希望它们完成,我只希望它们完成任务,然后循环,等待更多。我希望能够等待所有当前任务完成,这样我就可以安排更多的任务,而不必启动新线程,而是使用我已有的线程。join不会杀死线程,它会等待它们完成,但我不希望它们完成,我只希望它们完成任务,然后循环,等待更多。我希望能够等待所有当前任务完成,这样我就可以安排更多的任务,而不必启动新线程,而是使用我已经拥有的线程。你确实是对的,使用相同的锁(例如task_lock)即使没有“volatile”变量也能解决问题。我的问题有两个:1。volatile为什么/如何解决这个问题?2.为什么在ThreadPool::join()函数中锁定互斥锁不会阻止线程在Thread::threadLoop()中获取新任务?1。C++的代码语义>易失性几乎完全是实现定义的。对于MSVC,
volatile T
具有类似于C++11
std::atomic的acquire发布语义(请参阅)。2.这些是条件变量的语义:它们在被阻止时丢弃锁,并在检查条件时重新获取锁-所有这些都是“幕后的”(请参阅)。您确实是对的,使用相同的锁(例如task_lock)即使没有“volatile”变量也能解决问题。我的问题有两个:1。volatile为什么/如何解决这个问题?2.为什么在ThreadPool::join()函数中锁定互斥锁不会阻止线程在Thread::threadLoop()中获取新任务?1。C++的代码语义>易失性几乎完全是实现定义的。对于MSVC,
volatile T
具有类似于C++11
std::atomic的acquire发布语义(请参阅)。2.这些是条件变量的语义:它们在被阻止时丢弃锁,在检查条件时重新获取锁——所有这些都是“幕后的”(请参阅)。