【问题标题】:c++11 threads don't modify same valuesc++11线程不修改相同的值
【发布时间】:2014-08-03 05:12:46
【问题描述】:

我正在编写一个(理想情况下)需要两个线程同时运行的程序。

我有一个全局向量变量 myObjects 来跟踪我的对象:

vector<Object> myObjects;

还有一个 MoND 类型的对象,它将完成繁重的工作。 它以向量作为参数进行初始化,并将“对象”推入向量。到目前为止没有问题。

MoND  mySim =  MoND(myObjects);

在 main 中,需要以 myObjects 作为参数调用 mySim 的方法。 在我用于测试的非线程版本中,这是可行的(在 100 次迭代后运行退出):

int main(int argc, char** argv) {
  ...
  mySim.Run(myObjects);// Run simulation on Objects
  glutMainLoop();      // Enter the event-processing loop                                                                                            
  return 0;
}

我的意思是更改存储在myObjects 中的Objects 的属性。 这需要持续并同时运行,因此并不理想。

使用线程:

int main(int argc, char** argv) {
  ...
  thread t1(&MoND::Run, mySim, myObjects);// Run simulation on Objects
  glutMainLoop();      // Enter the event-processing loop                                                                                            
  return 0;
}

这并没有达到预期的效果。 Run() 接收 myObjects 并更改它们的值,但这些不会转换为主线程正在使用的 myObjects。是否在内存中为新线程创建了另一个 myObjects 实例? (是的,我确实通过引用传递,非线程版本确实更新了值)

所以我知道逻辑有效(一切都按预期工作,无需线程)。 我曾尝试使用 atomic,但老实说,我无法让它与矢量或其内容一起使用。

如何强制这两个线程在内存中myObjects 的同一个实例上工作(即让它们共享变量)?

几点:

  • 不,我不担心线程安全,因为只有一个线程写入,另一个只读取(读/写顺序不重要)

  • Run()通过SetPos(args..)SetVel(args..)方法更新Object类对象中私有变量的值

【问题讨论】:

  • std::thread 复制参数。使用std::ref。请注意,边读边写仍然会导致问题。
  • “不,我不担心线程安全,因为只有一个线程写入,另一个只是读取(读/写顺序不重要)”你可能应该是:并发访问同一个对象由两个线程 - 至少其中一个正在修改对象 - 是数据竞争。具有数据竞争的程序具有未定义的行为。

标签: c++ multithreading c++11


【解决方案1】:

std::thread 构造函数复制其参数以确保它们在被操作时仍然存在。

为避免这种情况,您可以使用std::ref:

thread t1(&MoND::Run, mySim, std::ref(myObjects));

在这里你保证你会照顾你的对象的生命周期。

std::bindstd::async 出于相同的原因表现出相同的行为。

注意mySim 也被复制了,但是如果不想复制,你也可以传递一个指针。

【讨论】:

  • 非常感谢,将研究 std::bind 和 std::ref 以备将来使用
【解决方案2】:

由于您要跨线程共享的变量是全局变量,因此解决方案更加简单:根本不要将其作为参数传递。

全局变量在整个程序中都是可见的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多