简短版:如何从单个线程释放多个锁,而不会在中途被抢占?
我有一个设计为在 N 核机器上运行的程序。它由一个主线程和N个工作线程组成。每个线程(包括主线程)都有一个可以阻塞的信号量。通常,每个工作线程在减少其信号量时都会被阻塞,并且主线程正在运行。但是,有时,主线程应该唤醒工作线程在一定时间内做他们的事情,然后阻塞自己的信号量,等待它们全部重新进入睡眠状态。像这样:
def main_thread(n):
for i = 1 to n:
worker_semaphore[i] = semaphore(0)
spawn_thread(worker_thread, i)
main_semaphore = semaphore(0)
while True:
...do some work...
workers_to_wake = foo()
for i in workers_to_wake:
worker_semaphore[i].increment() # wake up worker n
for i in workers_to_wake:
main_semaphore.decrement() # wait for all workers
def worker_thread(i):
while True:
worker_semaphore(i).decrement() # wait to be woken
...do some work...
main_semaphore.increment() # report done with step
一切都很好。问题是,其中一个被唤醒的工作线程可能会在唤醒工作线程的中途抢占主线程:例如,当 Windows 调度程序决定提高该工作线程的优先级时,就会发生这种情况。这不会导致死锁,但效率很低,因为其余线程保持休眠状态,直到抢占的工作人员完成其工作。它基本上是优先级反转,主线程在其中一个工作线程上等待,而一些工作线程在主线程上等待。
我可能会为此找出特定于操作系统和调度程序的技巧,例如在 Windows 下禁用优先级提升,以及摆弄线程优先级和处理器亲和力,但我想要一些跨平台的、健壮和干净的东西。那么:如何以原子方式唤醒一堆线程?