【问题标题】:C++ multi-threaded algorithm design for notify-wait pattern通知等待模式的 C++ 多线程算法设计
【发布时间】:2015-09-08 22:35:36
【问题描述】:

我正在寻找以下算法在 Windows 上的多线程实现的建议和代码示例:

  • 线程1:取input1,做工作,通知Thread2,继续工作。
  • 线程2:取input2,做工作,等待线程2的通知,做一些处理,通知Thread3,继续工作。
  • Thread3:取input3,做工作,等待thread3的通知,做一些处理,通知Thread4,继续工作。 等等。

由于我是 C++ 新手,我不确定选择哪种机制在线程之间发送/接收通知。
我考虑了几种方法:mutexsemaphorecritical section,但这些似乎主要用于锁定,而不是用于等待通知。

【问题讨论】:

  • 向我们展示你到目前为止所做的尝试。
  • 如果你在windows上,考虑使用Windows Events
  • 使用 Windows 事件会非常慢!只需使用一个简单的布尔值,并使用互斥锁进行保护,就可以了。
  • @ravenspoint 并没有那么慢,不过对于他想要的东西来说可能有点矫枉过正。
  • 互斥锁在这里也太过分了。请改用原子布尔值。原子也有它的成本,但更轻量级。

标签: c++ multithreading


【解决方案1】:

除了您已经列出的常用助手之外,您还应该看看condition variable

condition_variable 类是一个同步原语,可以 用于阻塞一个线程,或同时阻塞多个线程, 直到: - 从另一个线程收到通知 [...]

当使用条件变量时,线程 2 可以等到它被“通知”,以便线程 2 可以继续,依此类推。这是一个简单的例子:

std::mutex mtx;
std::condition_variable cv;
static bool ready = false;

static void set ()
{
  {
    std::unique_lock<std::mutex> lck(mtx);
    while (!ready)
      cv.wait(lck);
  }

  std::cout << "message received" << std::endl;
}

static void go()
{
  std::unique_lock<std::mutex> lck(mtx);
  ready = true;

  // here we set the condition variable for thread1
  cv.notify_all();
}

int main ()
{
  std::thread thread1 = std::thread(set);

  go();
  thread1.join();
  return 0;
}

【讨论】:

    【解决方案2】:

    假设每个线程的任务函数看起来像这样:

    void threadfunc()
    {
        MSG winmsg;
        BOOL rval;
    
        while (GetMessage(&winmsg, (HWND__ *) -1, 0, 0) != -1)
        {
            DoThreadProcessing();
        }
        // GetMessage failed. Find out why and try to recover or die gracefully
    }
    

    这会阻塞GetMessage,直到线程被下一个函数发送的消息唤醒

    bool PostMsg(DWORD & ThreadId)
    {
        if (PostThreadMessage(ThreadId,
                              WM_USER,
                              (WPARAM) NULL,
                              0); != 0)
        {
            return true;
        }
        else
        {
            // failed. Find out why and try to recover or die gracefully
            return false;
        }
    }
    

    通过PostThreadMessage 的魔力。

    如果你关心发送什么样的消息,你可以在Msg参数中发送简单的信息,比如一个数字,然后从winmsg.message中提取。保持较小的数字,因为 Windows 将message 的上半部分用于它自己的邪恶目的。

    如果您需要更复杂的消息传递,Mutex not correctly used? Continuation of past questions 涵盖了这一点。

    所以在 OP 的情况下,线程 1 使用线程 2 的句柄调用 PostMsg 以唤醒线程 2。线程 2 使用线程 3 的句柄调用 PostMsg,依此类推。

    您甚至可以使用std::threadnative_handle 方法将大部分时间留在标准库中,但我从未对此进行过测试。让我知道它是否有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-17
      • 2018-05-14
      相关资源
      最近更新 更多