【问题标题】:std::thread c++. More threads same data标准::线程 C++。更多线程相同的数据
【发布时间】:2013-02-26 01:51:41
【问题描述】:

我正在使用 Visual Studio 2012 和 C++11。我不明白为什么这不起作用:

void client_loop(bool &run)
{
    while ( run );
}

int main()
{
    bool running = true;
    std::thread t(&client_loop,std::ref(running));

    running = false ;
    t.join();
}

在这种情况下,线程t 的循环永远不会结束,但我明确地将running 设置为falserunrunning 具有相同的位置。我试图将running 设置为单个全局变量,但没有任何反应。我也尝试传递一个指针值,但什么也没有。

线程使用相同的堆。我真的不明白。谁能帮帮我?

【问题讨论】:

  • 您的程序过早终止,无法观察到任何有趣的事情。
  • 不,我忘了在这个例子中写“t.join()”.. :)
  • 如果将running 设置为volatile 会怎样?
  • @didierc:如果他将它设置为volatile,他可能会被欺骗以为他有工作代码。 Microsoft 定义了volatile,所以它可以工作,但标准不需要它。
  • @JerryCoffin thx,我想我之前的某个时候弄错了。我的立场是正确的。

标签: c++ multithreading c++11 heap-memory std


【解决方案1】:

您的程序有未定义行为,因为它在running 变量上引入了数据竞争(一个线程写入它,另一个线程读取它)。

您应该使用互斥锁来同步访问,或者将running 设置为atomic<bool>

#include <iostream>
#include <thread>
#include <atomic>

void client_loop(std::atomic<bool> const& run)
{
    while (run.load());
}

int main()
{
    std::atomic<bool> running(true);
    std::thread t(&client_loop,std::ref(running));

    running = false ;
    t.join();

    std::cout << "Arrived";
}

查看工作中的live example

【讨论】:

  • 谢谢你,我(愚蠢地)认为如果第二个线程只读取数据就不需要预防措施了。我不知道“原子”变量:但现在我发现我很高兴。再次感谢
  • @MatteoGaleotti 它甚至可能在合理的架构上工作过(当然,尽管仍然是 UB),但这个无限循环不是那么简单,只需优化即可。
  • 两个音符。首先,run 可能不应该被声明为const。诚然,编译器无法优化负载,但该函数仍然假定值发生了变化。其次,不需要.load()while (run) ; 也可以; run 在上下文中转换为bool,最终应用其operator bool()
  • @PeteBecker:关于load(),你是对的,谢谢你指出这一点。关于const,我把它放在那里是为了指定client_loop() 本身不会修改该值。放置const 是否也意味着该函数不希望值改变?我会说答案是“不”,但你的评论似乎暗示它是“是”。如果是这样,你能扩大一点吗?
【解决方案2】:

const 可能不会影响编译器对代码的查看。在单线程应用程序中,该值不会改变(并且这个特定程序毫无意义)。在多线程应用程序中,由于它是原子类型,编译器无法优化负载,所以实际上这里没有真正的问题。这实际上更多是风格问题。因为main 修改了该值,而client_loop 查找该修改,所以说该值为const 似乎不对。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多