2012-03-28 39 views
1

我正在实现一个条件变量的等待操作。我有我的条件变量的结构。到目前为止,我的结构有一个监视器,一个队列和一个自旋锁。但我不确定一个条件变量本身是否应该有一个队列。我通知如下所示:做条件变量是否有队列?

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

信号操作(即您打电话通知)不应要求输入显示器。这是低效的。

看起来你似乎试图实现一些笨拙的老式的条件/监视系统,其中“通知”的调用者必须在监视器内,并且保证如果一个线程在等待,那个线程获得在“通知”呼叫者返回监视器之前进行监视。 (并且那个等待的线程不必重新测试条件)

这可能是CAR Hoare最初如何描述监视器和条件,但形式化在现代多处理器系统上是不切实际/低效的,并且也可以用于线程实现,这些实现没有与低级别调度程序非常紧密地集成在一起(为了能够精确地控制哪个线程在什么时候运行,所以没有关于谁首先获得互斥量的比赛:例如,能够将线程从一个等待队列转移到另一个等待队列等)

请注意如何通过spinlock_lock操作和dequeue操作扩展显示器的临界区域。这些都不属于监视器。自旋锁是独立的,队列由自旋锁保护,而不是监视器。监视器应该只保护用户代码的共享变量(等待操作的特殊原子属性)。

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); 
} 

这将确保自旋锁总是被释放。

+0

所以你说显示器的队列就够了,我不需要另外一个队列来处理我的条件变量? – BBB 2012-03-28 20:05:00

+0

是的。如果您正确实施它,则不需要为条件变量本身设置单独的队列。 – Neo 2012-03-28 21:19:56