两次解锁条件变量互斥量?

Unlocking the condition variable mutex twice?

我正在查看以下片段:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cvar;
char buf[25];
void*thread_f(void *);

int main(){

    pthread_t thr; 
    pthread_cond_init(&cvar,NULL);
    pthread_mutex_lock(&mtx);
    pthread_create(&thr,NULL,thread_f,NULL);
    pthread_cond_wait(&cvar,&mtx);
    pthread_mutex_unlock(&mtx);
    ...join and destroy thread...
}

thread_f:

void* thread_f(void* argp){

    pthread_mutex_lock(&mtx);
    strcpy(buf,"test");
    pthread_cond_signal(&cvar);
    pthread_mutex_unlock(&mtx); //why?
    pthread_exit(NULL);
}

我对上面代码的理解是,main 获取锁,创建线程并运行 thread_f 阻塞。然后,main 发出等待条件变量 cvar 的信号并解锁互斥体。然后,thread_f 解锁,strcpys 和信号 cvar 唤醒。然后,main 和 thread_f 都解锁互斥量。

这是实际行为,还是我遗漏了什么地方?如果这是实际行为,则不会解锁已经解锁的互斥锁 UB,因此是否应该删除最后解锁的互斥锁之一?

谢谢。

主线程中的 pthread_cond_wait() 解锁互斥锁并等待条件被通知 — 并在返回前重新锁定互斥锁。

子线程能够锁定互斥锁,操作缓冲区,发出条件信号,然后解锁互斥锁,让主线程重新获得锁。

因此,代码是 well-behaved — 在具有多个子线程的更一般情况下,需要担心 'spurious wakeups'。我不认为你可以在这里得到一个虚假的唤醒。

这段代码的作用是有效的。

当线程调用pthread_cond_signal时,它不会立即导致主线程获取互斥量,而是唤醒主线程以便尝试锁定它。然后一旦线程释放了互斥量,主线程就可以锁定它并且 return from pthread_cond_wait.