1

我正在编写一个多线程应用程序。

我正在使用 boost::interprocess 类(版本 1.36.0)

本质上,我有工作线程需要在有工作可供他们执行时得到通知。

我尝试了“信号量”和“条件”两种方法。

在这两种情况下,工作线程的 CSwitch(上下文切换)似乎都非常高,例如每秒 600 次切换。

我看了一下代码,它似乎只是检查一个标志(原子地使用互斥锁),然后在下次重试之前产生时间片。

我期待代码使用 WaitForSingleObject 或其他东西。

具有讽刺意味的是,这正是我在决定“正确”使用并使用 Boost 之前的做法!(即使用互斥锁定期检查标志的状态)。唯一的区别是,在我的方法中,我在两次检查之间睡了 50 毫秒,所以我没有高 CSwitch 问题(是的,工作不会在 50 毫秒内开始对我来说很好)。

几个问题:

  1. 这个“高”的 CSwitch 值重要吗?
  2. 如果 boost 库使用 CRITICAL_SECTIONS 而不是信号量(我不关心进程间同步 - 所有线程都在同一个进程中),会发生这种情况吗?
  3. 如果 boost 使用 WaitForSingleObject 会发生这种情况吗?
  4. Boost 库中是否有另一种使用上述 Win32 等待方法 (WaitForXXX) 的方法,我认为它不会受到此 CSwitch 问题的影响。

更新:这是一个伪代码示例。我不能添加真正的代码,因为它会有点复杂。但这几乎就是我正在做的事情。这只是启动一个线程来执行一次性异步活动。

注意:这些只是插图!此示例中缺少负载,例如,如果您在线程达到“等待”之前调用 injectWork() 它将无法工作。我只是想说明我对 boost 的使用。

用法类似于:

int main(int argc, char** args)
{
  MyWorkerThread thread;
  thread.startThread();

  ...

  thread.injectWork("hello world");
}

这是使用 boost 的示例。

class MyWorkerThread
{
public:

  /// Do work asynchronously
  void injectWork(string blah)
  {
    this->blah = blah;

    // Notify semaphore
    this->semaphore->post();
  }

  void startThread()
  {
    // Start the thread (Pseudo code)
    CreateThread(threadHelper, this, ...);
  }

private: 


  static void threadHelper(void* param)
  {
    ((MyWorkerThread*)param)->thread();
  }

  /// The thread method
  void thread()
  {
    // Wait for semaphore to be invoked
    semaphore->wait();

    cout << blah << endl;
  }

  string blah;  
  boost::interprocess::interprocess_semaphore* semaphore;
};

这是我的“天真”轮询代码:

class MyWorkerThread_NaivePolling
{
public:

  MyWorkerThread_NaivePolling()
  {
    workReady = false;
  }

  /// Do work asynchronously
  void injectWork(string blah)
  {
    section.lock();

    this->blah = blah;
    this->workReady = true;

    section.unlock();
  }

  void startThread()
  {
    // Start the thread (Pseudo code)
    CreateThread(threadHelper, this, ...);
  }

private: 

  /// Uses Win32 CriticalSection
  class MyCriticalSection
  {
    MyCriticalSection();
    void lock();
    void unlock();
  };

  MyCriticalSection section;


  static void threadHelper(void* param)
  {
    ((MyWorkerThread*)param)->thread();
  }

  /// The thread method
  void thread()
  {
    while (true)
    {
      bool myWorkReady = false;
      string myBlah;

      // See if work set 
      section.lock();
      if (this->workReady)
      {
        myWorkReady = true;
        myBlah = this->blah;
      }
      section.unlock();

      if (myWorkReady)
      {
        cout << blah << endl;
        return;
      }
      else
      {
        // No work so sleep for a while
        Sleep(50);
      }
    }
  }

  string blah;  
  bool workReady;
};

干杯,

约翰

4

2 回答 2

3

在非 POSIX 系统上,它似乎interprocess_condition是使用循环来模拟的,正如您在问题中所描述的那样。Andinterprocess_semaphore用 mutex 和 an 进行模拟interprocess_condition,因此 wait()-ing 会在同一个循环中结束。

由于您提到不需要进程间同步,因此您应该查看Boost.Thread ,它提供了条件变量的可移植实现。有趣的是,它似乎是在 Windows 上以“经典”方式实现的,使用...信号量。

于 2009-10-15T19:18:06.647 回答
0

如果您不介意 Windows 特定(Windows 上的较新版本),请检查轻量级条件变量 CONDITION_VARIABLE的链接(如关键部分):

于 2009-10-14T10:11:39.450 回答