0

我希望有两个线程。第一个 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 条件变量,但发现线程 2 执行“通知线程 1 我很忙”与 thear2IsExclusive() 上的 waitForThread2() 中的循环之间的延迟可能长达近一秒。然后我尝试使用 volatile sig_atomic_t 共享变量来控制它,但是出了点问题,所以我一定没有正确地做。

4

3 回答 3

3

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

于 2010-05-25T02:16:25.403 回答
1

与其让你的线程互相告诉“我很忙”或“我不忙”,不如试着从你的线程正在操作的数据对象的角度来思考。

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

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

于 2010-05-25T02:27:44.473 回答
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

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

于 2010-05-25T02:35:10.353 回答