2017-04-01 95 views
13

我试图在以前worker_thread开始工作,但可能已结束或不结束时启动新线程。我已经替换了开始并结束了延时工作。我的代码是:C++条件变量通知不按预期方式工作

#include <iostream> 
#include <string> 
#include <mutex> 
#include <condition_variable> 
#include <future> 
#include <atomic> 
#include <chrono> 
#include <thread> 

std::mutex m; 
std::condition_variable cv; 
bool started = false; 

void worker_thread() 
{ 
    std::unique_lock<std::mutex> lk(m); 

    static std::atomic<int> count(1); 
    std::this_thread::sleep_for(std::chrono::milliseconds{(count % 5) * 100}); 
    std::cerr << "Start Worker thread: " << count << "\n"; 

    started = true; 
    lk.unlock(); 
    cv.notify_one(); 

    std::this_thread::sleep_for(std::chrono::milliseconds{3000}); 
    std::cerr << "Exit Worker thread: " << count << "\n"; 
    ++count; 
} 

int main() 
{ 
    while(1) { 
     std::async(std::launch::async, worker_thread); 
     std::unique_lock<std::mutex> lk(m); 
     cv.wait(lk, []{return started;}); 
     started = false; 
    } 
} 

输出看起来像这样:

Start Worker thread: 1 
Exit Worker thread: 1 
Start Worker thread: 2 
Exit Worker thread: 2 
Start Worker thread: 3 
Exit Worker thread: 3 
Start Worker thread: 4 
Exit Worker thread: 4 
Start Worker thread: 5 
Exit Worker thread: 5 

这不是我想要的行为。我想要的是像(不完全)这样的:

Start Worker thread: 1 
Start Worker thread: 2 
Start Worker thread: 3 
Start Worker thread: 4 
Exit Worker thread: 1 
Exit Worker thread: 3 
Exit Worker thread: 4 
Exit Worker thread: 2 
Start Worker thread: 5 
Exit Worker thread: 5 

目前的工作而以前的线程完成下一个线程才开始。但是,我想在上一个线程中开始工作并且不等待它结束时才开始下一个线程,只能等待开始。

回答

12

std::async返回一个std::future函数执行的保存结果。就你而言,它是一个被直接摧毁的临时对象。为std::future文档说:

these actions will not block for the shared state to become ready, except that it may block if all of the following are true

✔共享状态是通过调用创建到std ::异步

✔共享状态还没有准备好

✔这是共享状态的最后一个参考

所有这些都是真实的,所以破坏o f future将阻塞,直到工作器功能将完成执行。

您可以创建分离线程来避免这个问题:

std::thread(worker_thread).detach(); 
+2

还有其他的问题:如果cv.wait正在运行的通知将错过前cv.notify_one被调用。在提交的代码中,它很可能会。变量'started'在第一个worker_thread中设置为true,并保持此状态。 – CAF

+0

@CAF我忘了写在while循环结束时开始= false,已经更新了代码。但我不明白如何解决丢失的通知问题,我不能等待随机时间,因为启动事件可能需要任何时间量。 –

+0

@激光焦点:如果切换std :: async和std :: unique_lock语句在cv.wait之前,等待将在notify_one之前发生。 – CAF