【问题标题】:Sharing information between threads using mutex vs messages使用互斥锁与消息在线程之间共享信息
【发布时间】:2015-01-04 18:31:35
【问题描述】:

编辑:如果有人想试一试,我的问题仍然未回答

在我的 MFC C++ 应用程序中,我在 GUI 线程和工作线程之间共享信息,如以下代码所示。我创建了一个名为 inParams 的结构,它需要从主线程和工作线程中引用。因此,我声明它的成员为 std::atomic 类型,并且在原子类型不存在的情况下,例如。对于浮点数,我使用专用的互斥锁。主线程使用此信息执行操作Foo,工作线程执行操作BarFoo 和 Bar 同时运行,当用户更新它们时,它们都可以看到 param1 和 param2 的变化。

struct inParams{
    std::atomic_int param1;
    std::atomic_size_t param2;
    std::vector<customType> giantData;
    std::mutex giantDataMutex;
};

void myController::DoMainTask(){
    // Keep Handling GUI Events in this thread (main thread)
    // Create a Worker thread to do another task, I'll call it Bar
    SpawnWorkerThread()
}
void myController::SpawnWorkerThread(){
    std::thread t(&myController::tfunc, this);
    t.detach();
}
void myController::OnTimer(){  // say every 50 ms, just to simulate concurrency
    // When user changes param1 or param2, the changes affect here also
    Foo(inParams.param1, inParams.param2/* .. params list .. */);
}
void myController::tfunc(){
    while(1){
        // When user changes param1 or param2, the changes affect here also
        Bar(inParams.param1, inParams.param2, /* .. params list .. */); // 
    }
}

void myController::OnEventParam1(){ // User changed param1 in GUI
    inParams.param1 = GetValue( param1EditBox ); // GetValue gets value from Edit Box
}
void myController::OnEventParams2(){ // User changed param2 in GUI
    inParams.param2 = GetValue( param2EditBox );
}

我的问题是 - 这是一个反模式吗?我应该使用消息来共享此信息,而不是使用互斥锁(通过使它们成为原子)共享参数吗?

C++11 std::threads 是否允许消息传递,还是我应该依赖 WinAPI 的 PostThreadMessage API?

【问题讨论】:

  • 如果您不需要微秒级的响应时间,那么占用 CPU 来轮询原子以进行更改可能是矫枉过正。我会使用condition_variable 通知后台线程唤醒并查看更改的值。此外,detach 几乎是一种反模式。坚持std::thread 并拥有某种关闭协议通常会更好。 (即,您可能需要在 MyController 被销毁时停止线程)
  • @Casey '坚持 std::thread 并拥有某种关闭协议通常会更好' - 不,事实并非如此。

标签: c++ multithreading c++11 concurrency mfc


【解决方案1】:

您正在使用轮询/计时器来轮询共享变量。使用消息(PostMessage 和 PostThreadMessage)的优点是它消除了轮询并让线程成为事件驱动的。无论您是在消息中传递数据还是使用您拥有的同步访问权限,都没有关系。无论哪种方式都可以,但轮询很糟糕。

【讨论】:

  • 实际上,我使用计时器只是为了让 Foo 和 Bar 并发。在我的代码中,我实际上为此使用了 PostMessage。事件处理程序在文档类中,我对 View 类执行 PostMessage。我比较担心的是,由于inParams的GiantData成员是在两个线程之间共享的,会不会导致效率的损失或者意大利面条式的代码。我称它为 GiantData,因为它有数百兆字节。
猜你喜欢
  • 2017-05-04
  • 2014-12-18
  • 2021-10-10
  • 1970-01-01
  • 1970-01-01
  • 2013-11-24
  • 2021-07-28
  • 2012-06-10
  • 2013-12-17
相关资源
最近更新 更多