【问题标题】:c++ 11 Threads different behaviour on linux and windowsc++ 11个线程在linux和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 &lt;&lt; "some_function()\n"; 您在输出后缺少cout.flush(),这可能很好地解释了不同的行为。
  • 你想同步什么?目前,您正在同步对 std::cout 的访问,仅此而已。您的互斥锁只是保证您不会得到如下输出:“some_funsome_other_function\nction()\n”

标签: c++ linux windows multithreading c++11


【解决方案1】:

mutex 只是一个锁,用于防止对共享资源的并发访问,在本例中为 std::cout。在这两种情况下,一次只有一个线程写入std::cout。虽然在某些情况下解锁互斥锁可能会导致唤醒另一个任务,但除非您自己负责操作系统/调度程序代码,否则您不应该期望或依赖它。

互斥锁限制了对 std::cout 的访问:如果您在没有锁保护的情况下运行相同的代码,您可能会在一个操作系统或另一个操作系统上看到乱码/混合输出。

您在 Visual Studio 中看到类似内容的事实纯属巧合,不能保证,而且您在 Linux 下看到其他内容的事实更有可能是 IO 执行方式的差异而不是线程执行方式的差异操作。

我在推测您在这里实际尝试做什么,但我怀疑您想要condition_variablenotify_one。但是,您再次不应假设它会循环。

另外,joinable() 测试线程是否正在运行,join() 等待它们停止,但由于您的线程处于永久循环中,对join() 的第一次调用将永远挂起。

--- 编辑 ---

当我使用 /O2 在 Visual Studio 2015 下运行您的代码时,我得到的输出与您在 Linux 上报告的结果相同。

【讨论】:

  • 如果我们在两个或多个线程中有无限循环,那么如何加入它们?或者我们应该使用一些标志并基于一些条件变量我们应该继续?
  • 好吧,join 的意思是“等待退出”,如果你将while(1) 更改为for(size_t i = 0; i &lt; 10000; ++i),它们最终会结束,join() 会成功。 C++ 标准没有提供显式取消线程的方法。您可以使用std::shared_future&lt;void&gt; (en.cppreference.com/w/cpp/thread/shared_future) 作为通知您希望它们停止的线程的一种方式。见pastebin.com/uHVWSwyN
猜你喜欢
  • 2013-12-24
  • 2015-07-15
  • 2021-04-26
  • 2019-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多