我不知道 100% 喜欢你的提议,但有一些现有的接口很接近:
许多现有的读/写锁定 API 都有一个“尝试锁定”接口,例如 UN*X 系统上的pthread_rwlock_trywrlock()。这些是免等待的,只有在没有人拥有它或已经等待它的情况下才会获取锁。
您通常会使用这种旋转来锁定,和/或人为地延迟尝试代码(回退)。 IE。有这样的代码:
for (count = 0; count < MAX_SPINS && (locked = trywrlock(lock)); count++);
if (locked) {
delay(some_backoff);
wrlock(lock); /* or try spinning loop above again ? */
}
很遗憾,这并不是您所要求的;它会延迟锁定,但低优先级写入器将在 CPU 上旋转和/或由于(可能不必要的)退避而以延迟的方式获取它。
Solaris 内核有一个接口rw_tryupgrade(9f),可用于测试当前线程是否是锁上的唯一读取器,没有写入器等待,如果是,则将锁升级为独占/写入,即您将编写代码喜欢:
if (!rw_tryenter(lock, RW_WRITER)) {
rw_enter(lock, RW_READER); /* this might wait for a writer */
if (!rw_tryupgrade(lock)) { /* this fails if >1 reader / writer waiting */
/* do what you must to if you couldn't get in immediately */
}
}
这有点接近您的要求,但仍然不完全相同 - 如果失败,您必须放弃 readlock,可能后退(等待),重新获取 readlock,尝试升级。该过程再次相当于旋转。
此外,许多 UNIX 系统实际上至少按照调度优先级的顺序执行等待者唤醒;因此,在尝试普通的等待wrlock() 调用之前,您必须使线程的优先级最低(如果必要的话,人为地);根据调度程序的工作方式,在您的线程等待时想要相同的写锁的其他人将在此之前获得它。虽然在不一定保证的多处理器/核心系统上......
最后,SymbianOS(Symbian^3 版本)有一个RRWlock 类,可以使读者优先于写者,这样如果有读者等待/进来,它就会故意让写者饿死。同样,不完全准确您想要的行为,因为它会影响给定锁上的所有作者,而不仅仅是特定的。
恐怕您必须编写自己的优先级锁,并带有两个写入器唤醒队列。