c++ 11个线程在linux和windows上的不同行为
Posted
技术标签:
【中文标题】c++ 11个线程在linux和windows上的不同行为【英文标题】:c++ 11 Threads different behaviour on linux and windows 【发布时间】:2015-05-25 09:07:59 【问题描述】:#include <iostream>
#include <thread>
#include <mutex>
std::mutex mx;
void some_function()
while(1)
std::lock_guard<std::mutex> mx_guard(mx);
std::cout << "some_function()\n";
void some_other_function()
while(1)
std::lock_guard<std::mutex> mx_guard(mx);
std::cout << "some_other_function\n";
int main()
std::thread t1(some_function);
std::thread t2 = std::move(t1); //t2 will be joined
t1 = std::thread(some_other_function);
if(t2.joinable())
std::cout << "t2 is joinable()\n";
t2.join(); //calling join for t1
if(t1.joinable())
std::cout << "t1 is joinable()\n";
t1.join();
return 0;
我在 windows 和 linux 上对该程序有不同的输出。在使用 Visual Studio 13 编译器的 Windows 上,我得到以下输出。
some_function()
some_other_function
some_function()
some_other_function
some_function()
some_other_function
some_function()
some_other_function
some_function()
some_other_function
some_function()
some_other_function
但是在使用 gcc 的 linux 上输出是不同的
some_function()
some_function()
some_function()
some_function()
some_function()
some_function()
some_function()
some_other_function
some_other_function
some_other_function
some_other_function
some_other_function
some_other_function
some_other_function
在 windows 上,两个线程一个接一个地打印,但在 linux 上,它的行为不一样。在 linux 上使用互斥锁不同步。如何在linux上同步?
【问题讨论】:
您的系统有多少个 CPU?不保证线程之间的执行顺序。 “在 linux 上使用互斥锁不同步” - 您无法从该输出中得出结论。完全没有。 你究竟打算做什么?如果您提供的只是样板文件,我们将无法帮助您。std::cout << "some_function()\n";
您在输出后缺少cout.flush()
,这可能很好地解释了不同的行为。
你想同步什么?目前,您正在同步对 std::cout 的访问,仅此而已。您的互斥锁只是保证您不会得到如下输出:“some_funsome_other_function\nction()\n”
【参考方案1】:
mutex
只是一个锁,用于防止对共享资源的并发访问,在本例中为 std::cout。在这两种情况下,一次只有一个线程写入std::cout
。虽然在某些情况下解锁互斥锁可能会导致唤醒另一个任务,但除非您自己负责操作系统/调度程序代码,否则您不应该期望或依赖它。
互斥锁限制了对 std::cout 的访问:如果您在没有锁保护的情况下运行相同的代码,您可能会在一个操作系统或另一个操作系统上看到乱码/混合输出。
您在 Visual Studio 中看到类似内容的事实纯属巧合,不能保证,而且您在 Linux 下看到其他内容的事实更有可能是 IO 执行方式的差异而不是线程执行方式的差异操作。
我在推测您在这里实际尝试做什么,但我怀疑您想要condition_variable 和notify_one
。但是,您再次不应假设它会循环。
另外,joinable()
测试线程是否正在运行,join()
等待它们停止,但由于您的线程处于永久循环中,对join()
的第一次调用将永远挂起。
--- 编辑 ---
当我使用 /O2 在 Visual Studio 2015 下运行您的代码时,我得到的输出与您在 Linux 上报告的结果相同。
【讨论】:
如果我们在两个或多个线程中有无限循环,那么如何加入它们?或者我们应该使用一些标志并基于一些条件变量我们应该继续? 好吧,join
的意思是“等待退出”,如果你将while(1)
更改为for(size_t i = 0; i < 10000; ++i)
,它们最终会结束,join()
会成功。 C++ 标准没有提供显式取消线程的方法。您可以使用std::shared_future<void>
(en.cppreference.com/w/cpp/thread/shared_future) 作为通知您希望它们停止的线程的一种方式。见pastebin.com/uHVWSwyN以上是关于c++ 11个线程在linux和windows上的不同行为的主要内容,如果未能解决你的问题,请参考以下文章
Windows 与 Linux 上的 gSOAP C++ 代码