我目前对条件变量的理解是,所有阻塞(等待)的线程都被插入到一个基本的 FIFO 队列中,当调用 signal() 时,第一项被唤醒。
有没有办法修改这个队列(或创建一个新结构)来代替优先级队列?我已经考虑了一段时间,但大多数解决方案最终都受到 CV 和互斥体固有的现有队列结构的阻碍。
谢谢!
我目前对条件变量的理解是,所有阻塞(等待)的线程都被插入到一个基本的 FIFO 队列中,当调用 signal() 时,第一项被唤醒。
有没有办法修改这个队列(或创建一个新结构)来代替优先级队列?我已经考虑了一段时间,但大多数解决方案最终都受到 CV 和互斥体固有的现有队列结构的阻碍。
谢谢!
我认为你应该重新考虑你想要做什么。如果你试图优化你的表现,你可能会找错树。
pthread_cond_signal()
甚至不能保证完全解除阻塞一个线程——它保证至少解除阻塞一个线程,因此您的代码能够更好地处理多个线程同时解除阻塞的情况。执行此操作的典型方法是让每个线程在解除阻塞后重新检查条件,如果为假,则再次返回等待。
您可以实施某种方案,让您自己的线程优先级队列等待,每个线程在开始等待之前立即将自己添加到该队列中,然后在解除阻塞时检查队列,但这会增加很多复杂性和很多严重问题的可能性(竞争条件、死锁等)。它还增加了一笔不小的开销。
另外,如果一个更高优先级的线程在条件变量发出信号的同时开始等待一个条件变量,会发生什么?谁被解除阻塞,新到达的高优先级线程还是之前的最高优先级线程?
线程解除阻塞的顺序完全取决于内核的线程调度程序,因此您可以任其摆布。我什至不会假设 FIFO 排序。
由于条件变量基本上只是一个障碍,并且您无法控制等待线程的队列,因此没有真正的方法来应用优先级。假设等待线程将以 FIFO 方式运行是无效的。
结合原子、附加条件变量和所涉及的线程/优先级的预知识,您可以构建一个解决方案,其中信号线程将重新向主 CV 发出信号,然后在优先级 CV 上重新阻塞,但它肯定不会不是一个通用的解决方案。这也是我的想法,所以可能还有其他缺陷。
调度程序决定了哪个线程将运行。您可以查看pthread_setschedparam
和pthread_getschedparam
调整策略(SCHED_OTHER
、SCHED_FIFO
或SCHED_RR
)和优先级。但它可能不会让你到达我怀疑你想去的地方。
听起来好像您想从固有的非确定性中做出可预测的事情。正如 Andrew 指出的那样,您可能会破解某些东西,但我的猜测是,这会导致心痛或大量代码,您会讨厌自己在六个月内(或两者兼而有之)编写代码。