我正在实现一个条件变量的等待操作。我的条件变量有一个结构。到目前为止,我的struct有一个监视器,一个队列和一个自旋锁。但我不确定条件变量是否应该有一个队列本身。我的通知看起来像这样:
void uthread_cv_notify (uthread_cv_t* cv) {
uthread_t* waiter_thread;
spinlock_lock(&cv->spinlock);
waiter_thread = dequeue (&cv->waiter_queue);
if(waiter_thread)
{
uthread_monitor_exit(cv->mon);
uthread_stop(TS_BLOCKED);
uthread_monitor_enter(cv->mon);
spinlock_unlock(&cv->spinlock);
}
}
但是我想知道在通知函数或等待函数中我是否应该在监视器的等待队列中入队并出列?
由于
答案 0 :(得分:0)
那为什么你需要一个额外的队列?您已经存储了需要通知的所有线程。
另外,你可能想做这样的事情:
void uthread_cv_notify (uthread_cv_t* cv) { uthread_t* waiter_thread; spinlock_lock(&cv->spinlock); waiter_thread = dequeue (&cv->waiter_queue); if(waiter_thread) { uthread_monitor_exit(cv->mon); uthread_stop(TS_BLOCKED); uthread_monitor_enter(cv->mon); } spinlock_unlock(&cv->spinlock); }
这将确保始终释放自旋锁。
答案 1 :(得分:0)
信号操作(您正在呼叫通知)不应要求输入监视器。这是低效的。
好像你正在尝试实现一些笨拙的旧式条件/监控系统,其中“notify”的调用者必须在监视器内部,并且保证如果一个线程正在等待,该线程将获得监视器在“通知”调用者返回监视器之前。 (并且等待线程也不必重新测试条件的循环。)
这可能是CAR Hoare最初描述监视器和条件的方式,但形式主义在现代多处理器系统上是不切实际/低效的,而且在线程实现方面也没有与低级调度程序非常紧密集成的优点(至能够精确控制哪个线程何时运行,因此没有关于谁首先获取互斥锁的比赛:例如,能够将线程从一个等待队列传输到另一个等等队列,等等。)
请注意您是如何通过spinlock_lock
操作和dequeue
操作扩展监视器的关键部分。这些都不属于监视器。自旋锁是独立的,队列由自旋锁保护,而不是由监视器保护。监视器应该只保护用户代码的共享变量(等待操作的特殊原子属性)。