在线程调用 pthread_wait 现在发出信号后,执行发生在哪里?

Where does the execution happen after a thread has called pthread_wait is now signalled?

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;

void thread_1() {
    pthread_mutex_lock(&mutex); 
       some_cond = true;        
      pthread_cond_signal(&cv);    
    pthread_mutex_unlock(&mutex);       
}
void thread_2() {
    pthread_mutex_lock(&mutex);        
    while (!some_cond)              
        pthread_cond_wait(&cv, &mutex); 
    printf("test"); // After signaling from thread_1, does this get ran after?
    pthread_mutex_unlock(&mutex);       
}

假设 thread_2 调用 pthread_cond_wait.

Thread_1 出现然后 pthread_cond_signal.

我了解到 thread_2 会在调用 pthread_cond_wait 时被阻塞,并解锁其互斥量。 但是,我很困惑 thread_1 调用 signal 之后 thread_2 中的哪一行代码会 运行 .

thread_2中,当它被唤醒时,它是否从thread_2现在可以访问互斥锁的地方开始,然后锁定它,然后再次检查 while 条件,发现它现在为真并打印 test?

或者 thread_2 是否可以访问其互斥量,然后将其锁定,然后 print("test") 是 运行 之后(忽略while 条件)?

However, I am confuse on which line of code will run in thread_2 after thread_1 calls signal.

实际上,在thread_1调用pthread_cond_signal之后,什么也不会发生,因为thread_1仍然有互斥锁。 thread_1 上的下一条指令是 pthread_mutex_unlock。然后 thread_2 将停止阻塞 pthread_cond_wait 并自动 acquire 锁定。 while 条件然后将检查条件,中断并打印“测试”。

关于:

void thread_1() {

void thread_2() {

这些不是线程函数的有效签名!也许你的意思是:

void * thread_1( void *arg )

void * thread_2( void *arg )

另外,运行关闭线程结束函数无效。建议每个线程中的最后一个语句是:

pthread_exit( void );

无法保证哪个线程先运行。如果 thread_2() 先运行,那么互斥量将被锁定并且 thread_2() 将永远等待 pthread_condition(),但由于 thread_1() 将立即被阻止试图获得互斥锁。 NOTHING(更多)将在这些线程中执行。

通常,函数:pthread_wait() 在可执行文件的同一部分调用函数:pthread_create()。这会暂停调用代码,直到某个线程退出(在上面的场景中,没有线程会退出

调用pthread_cond_signal时,另一个线程中没有特定的代码行运行。如果您希望特定行以特定顺序 运行,则必须将所有这些行放入一个线程的路径中。

当调用 pthread_cond_signal 时,另一个线程几乎可以做任何事情。我们知道的一件事是, 因为信号调用在互斥体内部,所以另一个线程不在互斥体中。我们可以标记其他可以的地方:

void thread_2() {
    // (A) Either here, or earlier.
 
    pthread_mutex_lock(&mutex);        
    while (!some_cond)              
        pthread_cond_wait(&cv, &mutex); // (B) Or here. 
    printf("test"); // After signaling from thread_1, does this get ran after?
    pthread_mutex_unlock(&mutex);  

    // (C) Or else here, or farther 
}

只有当 some_cond 已经为真时,另一个线程才能位于 C。如果 some_cond 假设为假,我们可以忘记 C.

如果 A 是这种情况,则线程要么正在执行 pthread_mutex_lock 之前的代码(我们可以称其为 A1),要么它已经锁定并且现在等待互斥锁 (A2).

调用 pthread_cond_signal 的线程拥有互斥锁,并在调用后继续这样做。所以有可能另一个线程在 A1,然后继续 A2(等待互斥体)。

如果线程处于B:等待条件变量,信号可能会唤醒它。在从 pthread_cond_wait returning 之前,它必须 re-acquire 互斥锁,所以它可能会卡在那里等待。在任何情况下,在 B 状态下,在第一个线程执行 pthread_mutex_unlock.

之前,另一个线程无法从 pthread_cond_wait 调用中 return

有可能另一个线程处于A1状态(还没有达到互斥量),而信号器完成了一切:设置变量,发出信号,释放互斥量。然后另一个线程会不等待就去抢这个互斥锁,看到条件为真,就离开这个互斥锁。信号是无关紧要的,因为 pthread_cond_wait 永远不会被调用。

如果您正在使用共享变量和显式同步原语(如互斥锁和条件)进行编程,则必须推理所有可能发生的情况:其他线程可能处于的所有相关状态。

其他几个例子都很好,但它们似乎都掩盖了我认为是 OP 的关键混淆点。

I am confuse on which line of code will run in thread_2 after thread_1 calls signal.

这里没有魔法。 pthread_cond_wait() 是一个函数,它的行为就像一个函数。当它的等待结束,并且它重新获得了互斥量时,它 returns 给它的调用者。控制从那里正常进行,就像在任何其他函数调用之后一样 returns.

在这种特殊情况下,函数调用是 while 循环主体中的唯一语句,因此调用 returns 之后发生的下一件事将是 while 正在重新评估条件。

请注意,pthread_cond_wait 的调用者可以而且应该检查 return 值以捕获和处理它指示发生错误的情况,就像对指示错误的其他函数所做的一样通过它们的 return 值的错误条件。