如何多线程这个?

时间:2010-05-25 02:10:46

标签: c++ pthreads mutex condition-variable

我希望有两个主题。第一个thread1偶尔会调用以下伪函数:

void waitForThread2() {
  if (thread2 is not idle) {
    return;
  }
  notifyThread2IamReady(); // i.e. via 1st condition variable
  Wait for thread2 to finish exclusive access. // i.e. via 2nd condition variable.
}

第二个thread2永远处于以下伪循环中:

for (;;) {
  Notify thread1 I am idle.
  Wait for thread1 to be ready. // i.e. via 1st condition variable.
  Notify thread1 I am exclusive.
  Do some work while thread1 is blocked.
  Notify thread1 I am busy. // i.e. via 2nd condition variable.
  Do some work in parallel with thread1.
}

写这个的最佳方法是使thread1和thread2在具有多个内核的机器上保持尽可能繁忙。我想避免一个线程中的通知和另一个线程的检测之间的长时间延迟。我尝试使用pthread条件变量,但发现thread2做'通知thread1我很忙'和在for2IsExclusive()上waitForThread2()中的循环之间的延迟可能达到差不多一秒的延迟。然后我尝试使用volatile sig_atomic_t共享变量来控制它,但是出了点问题,所以我一定不能正确地做。

3 个答案:

答案 0 :(得分:3)

看起来你应该使用信号量来发送信号,而不是让“while”循环空闲线程,等待某些条件发生。空闲循环很糟糕。

答案 1 :(得分:1)

不要让你的线程告诉对方“我很忙”或“我不忙”,而是试着考虑你的线程正在操作的数据对象。

如果有一些数据(例如计数器),两个线程可能会同时尝试更改,这意味着您需要一个互斥锁。

当线程更改其他线程可能正在等待的共享数据状态时,请发出条件变量信号以通知它们。 (例如,如果Producer线程将数据添加到队列,它可能会发出“dataAvailable”条件的信号,消费者可能正在等待该条件。)

答案 2 :(得分:1)

我向你看,就像你正在尝试做一个约会(Ada的一个术语)。

第二个线程正在等待第一个线程调用它,然后它在第一个线程等待时立即执行一些工作,并在第一个线程完成后再执行一些工作。

第一个线程是“调用”第二个线程 - 如果第二个线程无法接听电话,则立即超时。

Ada直接在语言中支持这一点,但假设移植到Ada不是一个选项......

这可以用三个信号量实现。信号量1表示线程1准备好会合。信号量2表示线程2已准备好进行重新对话。信号量3表示会合已完成。

线程1:获取信号量1的默认值。

 if Semaphore 2.acquire(timeout = 0) is successful # Thread 2 is ready
     Semaphore 1.release() # Indicate I am ready
     Semaphore 3.acquire() # Wait until the rendevous is complete.
     Semaphore 3.release()
     Semaphore 1.acquire() # Indicate I am not ready
     Semaphore 2.release() # I am no longer using thread 2.

 Do concurrent work 

线程2:获取信号量2的默认值。

 Loop forever
     Semaphore 3.acquire() # Indicate Rendevous is not complete.
     Semaphore_2.release() # Indicate I am ready
     Semaphore_1.acquire() # Wait for Thread 1 to be ready
     Joint processing
     Semaphore 1.release() # I am no longer using thread 1.
     Semaphore 3.release() # Rendevous is complete.
     Semaphore 2.acquire() # I am not ready

 Post-processing

注意:从头开始编写,未经测试。看起来比我想象的要复杂得多;我错过了什么吗?