这里的困难不是优先级,而是你希望一个线程退出它所持有的锁,让另一个线程拿走它。“优先级”与应该安排运行一组可运行线程中的哪一个有关——你想让一个线程不是可运行的(因为它正在等待另一个线程持有的锁)。
所以,你想实现(如你所说):
if (ThisThreadNeedsToSuspend()) { ReleaseDiskLock(); WaitForResume(); ReacquireDiskLock(); }
由于您(明智地)使用范围锁,我想反转逻辑:
while (file_is_not_finished) {
WaitUntilThisThreadCanContinue();
CritSecLock diskLock(blah);
process_part_of_the_file();
}
ReleasePriority();
...
void WaitUntilThisThreadCanContinue() {
MutexLock lock(thread_priority_mutex);
while (thread_with_priority != NOTHREAD and thread_with_priority != thisthread) {
condition_variable_wait(thread_priority_condvar);
}
}
void GiveAThreadThePriority(threadid) {
MutexLock lock(thread_priority_mutex);
thread_with_priority = threadid;
condition_variable_broadcast(thread_priority_condvar);
}
void ReleasePriority() {
MutexLock lock(thread_priority_mutex);
if (thread_with_priority == thisthread) {
thread_with_priority = NOTHREAD;
condition_variable_broadcast(thread_priority_condvar);
}
}
阅读条件变量——所有最近的操作系统都有它们,具有类似的基本操作。它们也在 Boost 和 C++11 中。
如果你不可能编写一个函数process_part_of_the_file
,那么你就不能以这种方式构造它。相反,您需要一个可以释放和重新获得磁盘锁的作用域锁。最简单的方法是使其成为互斥体,然后您可以使用相同的互斥体等待 condvar。您仍然可以thread_with_priority
以几乎相同的方式使用 mutex/condvar 对和对象。
您可以根据您需要系统对优先级更改的响应程度来选择“文件的一部分”的大小。如果您需要它具有极强的响应能力,那么该方案就无法真正发挥作用——这是协作式多任务处理。
我对这个答案并不完全满意,如果有很多其他线程已经在同一个磁盘锁上等待,那么具有优先级的线程可能会饿死很长时间。为了避免这种情况,我会考虑更多。可能不应该有每个磁盘的锁,而是应该在条件变量及其关联的互斥锁下处理整个事情。不过,我希望这能让你开始。