这个螺纹1函数似乎未执行

#包括<iostream>#包括<fstream#包含<线程>#包含<条件变量>#包括<队列>标准::condition_variable cv;std::mutex mu;std::queue<int>queue;bool ready;静态空心螺纹1(){while(!ready){标准::thisthread::sleep_for(标准::计时::毫秒(10));}while(ready&&queue.size()<=4){std::unique_lock<std::mutex>lk(mu);cv.wait(lk,[&]{return!queue.empty();});队列推送(2);}}整型main(){就绪=假;标准::螺纹t(螺纹1);while(queue.size()<=4){{标准::lock_guard<标准::mutex>lk(mu);queue.prush(1);}就绪=真;通知();}t.join();for(int i=0;i<=queue.size();i++){int a=queue.front();标准::cout<<a<<std::endl;queue.pop();}返回0;}

在我的Mac上,输出是1 2 1 2但在我的乌班图1 1 1。我正在编译g++-std=c++11-pthread-o thread.out thread.cpp&&/螺纹.外螺纹。我是不是错过了什么?

7
  • 无法保证thread1能够在主循环再次锁定互斥锁之前获取互斥锁。这就是多线程的运行方式,它可能是不可预测的。 评论 2017年4月10日3:28
  • 但我认为thread1中的条件变量会用wait锁定互斥锁,并同步main和thread1。我可以做什么来同步以按顺序运行?
    – 9月
    评论 2017年4月10日3:32
  • 你有比赛条件。螺纹1可以执行queue.size()虽然主要的执行队列推送(1),并且行为未定义。 评论 2017年4月10日3:33
  • 好的,我给thread1添加了一个带有sleep的就绪检查,以防止出现未定义、更新的代码。但种族条件仍然存在。
    – 9月
    评论 2017年4月10日3:39
  • 您正在访问准备好的来自两个单独的线程,但准备好的不考虑原子的.访问非-原子的多线程的值不安全/不明智/(可能是UB?)
    – 塔斯
    评论 2017年4月10日3:57

2个答案2

重置为默认值
2

这个:

for(int i=0;i<=queue.size();i++){int a=queue.front();标准::cout<<a<<std::endl;queue.pop();}

是未定义的行为。从0到的for循环大小大小+1时间。我建议您以更为惯用的方式为队列编写以下内容:

while(!queue.empty()){int a=queue.front();标准::cout<<a<<std::endl;queue.pop();}

当我在coliru上运行这个时,我假设它运行某种*nix机器,得到4个1:http://coliru.stacked-crooked.com/a/8de5b01e87e8549e.

同样,您没有指定任何会强制每个线程运行一定时间的内容。您只(尝试*)在队列大小达到4的位置产生一个不变量。碰巧,在我们运行它的机器上,线程2从未获得互斥锁。

如果您在不同的时间点添加更多的工作,甚至(仅出于教学目的)延迟,那么这个示例将更加有趣。模拟这两个线程实际在工作。如果您在不同的点添加sleep,则可以确保这两个螺纹交替,但这取决于您添加它们的位置,您可能会看到线程中断中4个元素的不变量!

*请注意,即使队列上的4个元素不变,也不是真正的不变。这是可能的(尽管可能性很小)二者都当队列中有3个元素时,线程在同一时刻传递while条件。其中一个先获得锁并按下,然后是另一个。所以你可以在队列中得到5个元素!(正如您所见,异步编程很棘手)。特别是,当您有锁时,您确实需要检查队列大小,以便使其正常工作。

0

我可以通过让第二个线程在单独的条件变量上等待单独的谓词来解决这个问题。我不确定queue.size()是否是线程安全的。

#包括<iostream>#包括<fstream#包含<线程>#包含<条件变量>#包括<队列>标准::condition_variable cv;标准::condition_variable cv2;std::mutex mu;std::queue<int>queue;滴答声;bool tock;静态空心螺纹1(){while(queue.size()<6){标准::unique_lock<标准::mutex>lk(mu);cv2.wait(lk,[]{return tock;});队列推送(1);tock=假;勾选=真;通知();}}整型main(){勾选=假;tock=真;标准::螺纹t(螺纹1);while(queue.size()<6){标准::unique_lock<标准::mutex>lk(mu);cv.wait(lk,[]{return tick;});队列推送(2);勾选=假;tock=真;cv2.notify_one();}t.join();while(!queue.empty()){int r=queue.front();queue.pop();标准::cout<<r<<std::endl;}返回0;}

你的答案

单击“发布您的答案”,表示您同意我们的服务条款并确认您已阅读我们的隐私政策.

不是你想要的答案吗?浏览已标记的其他问题问你自己的问题.