当我在按住相应的互斥锁时唤醒一个等待条件变量的线程时,我可以假设在我释放互斥锁之后以及其他任何人(包括我自己)可以再次锁定互斥锁之前,唤醒线程将会运行吗?或者我可以确定它将来会在某个时刻运行吗?
准确地说,假设我有以下功能。
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()
我是否可以在enter()
中获取互斥锁后直接确定(请参阅代码中的注释),如果taken
为false waiting
必须为零? [在我看来应该是这种情况,因为唤醒线程将假设找到唤醒线程留下的状态(如果唤醒不是假的),否则这可能无法保证,但我做了在任何地方都找不到明确的措辞。]
我主要对(现代)Linux上的行为感兴趣,但当然知道这是否由POSIX定义也会引起关注。
注意:这可能已在another question中提出,但我希望我的更清楚。
t0
执行pthread_cond_signal
后,t1
不再等待条件变量,但它也没有运行,因为t0
仍然保留互斥锁;而t1
正在等待互斥锁。线程t2
也可能在enter()
的开头等待互斥锁。现在t0
释放互斥锁。 t1
和t2
都在等待它。 t1
是以特殊方式处理并保证获得它,还是t2
可以获得它?
答案 0 :(得分:1)
感谢您的评论,Carsten,清理了它。
不,请参阅此answer以获取更多参考。根据您的示例,t2
可以在t1
之前获取互斥锁,并且可能会出现竞争条件,从而导致意外结果。
重申,t0
最初可能具有互斥锁并且位于行pthread_cond_wait(&c, &m);
上的while循环中,并且互斥锁以原子方式释放reference。 t1
可以调用leave()
获取发送条件c
的互斥锁,然后释放互斥锁。 t0
将尝试通过--waiting
获取现已释放的互斥锁来准备运行t1
,但它可以由操作系统进行上下文切换。等待互斥锁的其他线程t2
可以抓取并运行enter()
导致意外结果,请参阅non-reentrant。 t2
然后释放互斥锁。 t0
可能会回退,只是看到价值已经发生变异。