c - 通过条件变量唤醒的线程何时运行?

标签 c multithreading pthreads condition-variable

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

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

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 为 false waiting 必须为零? [在我看来应该是这种情况,因为被唤醒的线程将假设找到唤醒线程已经留下的状态(如果唤醒不是虚假的),否则无法保证,但我做到了在任何地方都找不到它的明确措辞。]

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

注意:这可能已经在 another question 中提出过, 但我希望我的更清楚。


t0做完pthread_cond_signal后,t1不再等待条件变量,但也没有运行,因为 t0 仍然持有互斥锁; t1 而是等待互斥量。线程 t2 也可能在 enter() 开始时等待互斥锁。现在 t0 释放互斥体。 t1t2 都在等待它。 t1 是否以特殊方式处理并保证获取它,或者 t2 是否可以获取它?

最佳答案

感谢您的评论,Carsten,这澄清了一切。

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

重申,t0 最初可能有互斥锁,并且在 while 循环中保持在 pthread_cond_wait(&c, &m); 行上,并且互斥锁以原子方式释放 referencet1 可以调用 leave() 获取互斥信号条件 c,然后释放互斥信号。 t0 将尝试通过 t1 获取现在释放的互斥锁来准备运行 --waiting,但它可以成为操作系统切换的上下文.等待互斥锁的一些其他线程 t2 可以获取它并运行 enter() 导致意外结果,请参阅 non-reentrantt2 然后释放互斥体。 t0 可能会交换回来,只是为了查看值是否发生了变化。

关于c - 通过条件变量唤醒的线程何时运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44417242/

相关文章:

java - 在Java中,如果我调用一个从另一个可运行对象扩展Thread的类,哪个Thread会执行?

c++ - 单线程和多线程代码同时耗时

c - (mysql_real_query) 在插入一些记录时中断

python - C zlib crc32 和 Python zlib crc32 不匹配

c - Unix ipc 服务器在一个客户端停止后停止

c - 如何使用 printf 重复一个字符?

android - Espresso 测试被后台线程阻塞。应用程序未空闲异常 : "AppNotIdleException."

ruby-on-rails - 在 ruby​​ 中通过并行处理有序插入数据

c++ - 无法在 pthread_create 函数中将 '*void(MyClass::*)(void*) 转换为 void*(*)(void*)

linux - NPTL 默认堆栈大小问题