线程何时会通过条件变量 运行 唤醒?

When will a thread woken via a condition variable run?

当我唤醒一个等待条件变量并持有相应互斥量的线程时,我可以假设被唤醒的线程将 运行 在我释放互斥量之后并且在任何其他人(包括我自己)可以锁定之前又是互斥体?或者我只能确定它会 运行 在未来的某个时候?

准确地说,假设我有以下功能。

bool taken = false;
int waiting = 0;

pthread_mutex_t m;   // properly initialised elsewhere
pthread_cond_t c;

void enter() {
    pthread_mutex_lock(&m);
    // Is `taken || (waiting == 0)` guaranteed here? 
    while (taken) {
        ++ waiting;
        pthread_cond_wait(&c, &m);
        -- waiting;
    }
    taken = true;
    pthread_mutex_unlock(&m);
}

void leave() {
    pthread_mutex_lock(&m);
    taken = false;
    if (waiting > 0) {
        pthread_cond_signal(&c);
    }
    pthread_mutex_unlock(&m);
}

(这是一个玩具示例,并不意味着有用。)

还假设所有线程都在使用这些函数作为

enter()
// some work here
leave()

如果 taken 为假,我能否直接在 enter() 中获取互斥锁(参见代码中的注释)后确定 waiting 必须为零? [在我看来应该是这种情况,因为被唤醒的线程将假设找到唤醒线程已经留下的状态(如果唤醒不是虚假的),否则无法保证,但我做到了在任何地方都找不到明确的措辞。]

我主要对(现代)Linux 上的行为感兴趣,但当然知道这是否由 POSIX 定义也会很感兴趣。

注意:another question中可能已经有人问过这个问题,但我希望我的更清楚。


t0pthread_cond_signal后,t1不再等待条件变量,但也不是运行ning,因为t0仍然持有互斥锁; t1 而是在等待互斥量。线程 t2 也可能在 enter() 的开头等待互斥体。现在 t0 释放互斥量。 t1t2 都在等待它。 t1 是以特殊方式处理并保证获得它,还是可以 t2 获得它?

感谢您的评论,卡斯滕,这让事情变得清晰起来。

不,请参阅此 answer 以获取更多参考。鉴于您的示例,t2 可以在 t1 之前获取互斥锁,并且可能会出现竞争条件,从而导致意外结果。

重申,t0 最初可能有互斥锁,并在 while 循环中保持在行 pthread_cond_wait(&c, &m); 上,并且互斥锁被自动释放 reference. t1 could call leave() acquiring the mutex signaling the condition c, and then release the mutex. t0 will prepare to run --waiting by trying to acquire the now-freed mutex by t1, but it can become context switched by the OS. Some other thread t2 waiting on the mutex can grab it and run enter() causing undesired outcomes, see non-reentrantt2 然后释放互斥锁。 t0 可能会交换回来,只是为了查看值是否发生了变化。