You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pthread多线程同步疑问:thread2持锁wait后thread1为何能加锁?

pthread多线程同步疑问解答

一、为什么thread2调用pthread_cond_wait后,thread1能成功获取互斥锁?

你误解了pthread_cond_wait的行为,它并非仅让线程阻塞,而是原子性地完成两个关键操作:

  • 自动释放传入的互斥锁mutex
  • 阻塞当前线程,等待条件变量的唤醒信号

所以当thread2执行到pthread_cond_wait(&cond,&mutex);时,已经主动释放了之前锁住的mutex,此时thread1调用pthread_mutex_lock(&mutex)自然能成功获取锁,完全符合手册描述。

当thread1调用pthread_cond_signal(&cond)后,thread2会被唤醒,此时它会重新获取mutex锁,之后才会继续执行printf("thread2: wait 2 %d\n", __LINE__);后续代码。

二、pthread_cond_signal的作用,以及能否用额外互斥锁替代?

1. pthread_cond_signal的核心作用

它用于通知等待在条件变量上的线程:特定条件已满足,让阻塞的线程唤醒并重新检查条件。

条件变量的设计是为了解决「线程需要等待某个条件成立」的场景(比如生产者-消费者模型中,消费者等待队列非空),优势在于:

  • 避免线程忙等(无需循环加锁检查条件,节省CPU资源)
  • 保证「条件检查+等待」的原子性,彻底规避竞态条件

2. 无法用额外互斥锁替代

如果试图用额外互斥锁在signal位置加锁、wait位置解锁,会引发诸多问题:

  • 竞态条件:thread2解锁额外互斥锁后开始等待,若此时thread1还未加锁,条件已满足,thread2会错过该变化,持续阻塞。
  • CPU浪费:线程需不断加锁轮询条件,无法高效休眠,占用冗余CPU资源。
  • 逻辑混乱:互斥锁的核心是保护共享资源的互斥访问,强行用于条件通知会让代码逻辑复杂且极易出错。

完整测试代码

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

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化条件变量*/

void *thread1(void *);
void *thread2(void *);

int i=1;

int main(void)
{
    pthread_t t_a;
    pthread_t t_b;
    pthread_create(&t_a,NULL,thread1,(void *)NULL);/*创建线程t_a*/
    pthread_create(&t_b,NULL,thread2,(void *)NULL); /*创建线程t_b*/
    pthread_join(t_a, NULL);/*等待线程t_a结束*/
    pthread_join(t_b, NULL);/*等待线程t_b结束*/
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    exit(0);
}

void *thread1(void *junk)
{
    for(i=1;i<=6;i++)
    {
        printf("djh: Line: %d, i = %d\n", __LINE__, i);
        pthread_mutex_lock(&mutex);/*锁住互斥量*/
        printf("thread1: lock %d\n", __LINE__);
        if(i%3==0){
            printf("thread1:signal 1 %d\n", __LINE__);
            pthread_cond_signal(&cond);/*条件改变,发送信号,通知t_b线程*/
            printf("thread1:signal 2 %d\n", __LINE__);
            printf("%s will sleep 1s in Line: %d \n", __FUNCTION__, __LINE__);
            sleep(1);
        }
        pthread_mutex_unlock(&mutex);/*解锁互斥量*/
        printf("thread1: unlock %d\n", __LINE__);
        printf("%s will sleep 1s in Line: %d \n\n", __FUNCTION__, __LINE__);
        sleep(1);
    }
}

void *thread2(void *junk)
{
    while(i<6)
    {
        printf("djh: Line: %d, i = %d\n", __LINE__, i);
        pthread_mutex_lock(&mutex);
        printf("thread2: lock %d\n", __LINE__);
        if(i%3!=0){
            printf("thread2: wait 1 %d\n", __LINE__);
            pthread_cond_wait(&cond,&mutex);/*解锁mutex,并等待cond改变*/
            printf("thread2: wait 2 %d\n", __LINE__);
        }
        pthread_mutex_unlock(&mutex);
        printf("thread2: unlock %d\n", __LINE__);
        printf("%s will sleep 1s in Line: %d \n\n", __FUNCTION__, __LINE__);
        sleep(1);
    }
}

内容的提问来源于stack exchange,提问作者Gerrie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 01:50:25