linux 条件变量 互斥锁的实现

通过两个线程模拟猴子吃桃过程:一个线程模拟桃树生长桃子,另一个线程模拟猴子吃桃。使用互斥锁和条件变量确保线程同步。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是一个经典的猴子吃桃子的问题的实现(生产-消费者问题)

  有一棵桃树和一只猴子,开始的时候桃树上没有桃子,然后开始一个一个的长,每长一个猴子就吃一个,猴子吃了之后再长一个,又被猴子吃掉,猴子需要吃7个桃子,才能吃饱。编写程序模拟这个猴子吃桃子的过程。
  一看这肯定是两个线程,一个是桃树长桃子,一个是猴子吃桃子,归根是一个生产者和消费者的问题。

注意事项

互斥锁用起来比较简单,条件变量会有点东西
条件变量其实就是一种通知,等待机制,要学会用这种机制去解决问题,语法也是相当之简单的,看下面这个代码就可以了

注意的是pthread_cond_wait 这个里面,可以理解是把锁借出去了的感觉~

代码

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

#define COUNT 7   // 一共需要吃多少桃子  

static int int_grow_number = 0;  // 已经长了多少桃子  
static int int_eat_number = 0; // 已经吃了多少桃子  

pthread_mutex_t lock;  
pthread_cond_t can_eat;// 猴子可以吃桃子了。  
pthread_cond_t can_grow; // 桃树需要长桃子  

void *eat(void *data)  
{  
    int n;  
    while(1)  
    {   
        pthread_mutex_lock(&lock);  
        if(int_grow_number == int_eat_number){  
            pthread_cond_wait(&can_eat, &lock); // 已经吃完所有的桃子  
        }  
        if(int_grow_number == -1){  
            printf("本猴子已经吃饱\n");  
        }else{  
            int_eat_number ++;  
            printf("猴子正吃第 (%d) 个桃子\n",int_eat_number);  
        }  
        sleep(1);  
        pthread_cond_signal(&can_grow);  //通知桃树长桃子  
        pthread_mutex_unlock(&lock);  
        if(int_grow_number == -1)  
            break;  
    };  
    return NULL;  
}  


void *grow(void *data)  
{  
    while (1)  
    {  
        pthread_mutex_lock(&lock);  
        if(int_grow_number >= int_eat_number+1){  
            pthread_cond_wait(&can_grow, &lock); // 等待猴子吃桃子  
        }  

        if(int_grow_number >= COUNT){ // 检查猴子是否吃饱了  
            int_grow_number = -1; // 没得吃了  
            printf("本次喂食结束 \n");  
        }else{  
            int_grow_number ++;  
            printf("桃树正长第 (%d) 个桃子 \n",int_grow_number);  
        }  
        pthread_cond_signal(&can_eat); // 通知猴子可以吃桃子  
        pthread_mutex_unlock(&lock);  
        if (int_grow_number == -1)  
            break;  
    }  
    return NULL;  
}  

int main(void)  
{  
    pthread_t th_peach, th_monkey;  
    void *retval;  
    pthread_mutex_init(&lock, NULL);  
    pthread_cond_init(&can_eat, NULL);  
    pthread_cond_init(&can_grow, NULL);  

    pthread_create(&th_peach, NULL, grow, 0);  
    pthread_create(&th_monkey, NULL,eat, 0);  

    /* 等待猴子吃饱,结束*/  
    pthread_join(th_peach, &retval);  
    pthread_join(th_monkey, &retval);
    pthread_mutex_destroy(&lock);
    pthread_cond_destroy(&can_eat);
    pthread_cond_destroy(&can_grow);
    return 0;  
}  
### 条件变量互斥锁的使用场景及主要区别 #### 使用场景分析 条件变量互斥锁都是线程同步机制中的重要工具,但在实际应用中有不同的侧重点。 - **互斥锁**主要用于保护临界区资源,确保同一时刻只有一个线程可以访问共享数据。它适用于需要防止多个线程同时修改同一个资源的情况[^1]。 ```c pthread_mutex_lock(&mutex); // 访问或修改共享资源 pthread_mutex_unlock(&mutex); ``` - **条件变量**则通常用来实现线程间的通信,尤其是在某些特定条件下才允许某个线程继续执行的情况下。例如,在生产者-消费者模型中,当缓冲区为空时,消费者线程会被阻塞直到有新的数据可用[^2]。 ```c pthread_cond_wait(&cond, &mutex); ``` #### 主要区别对比 | 特性 | 互斥锁 | 条件变量 | |---------------------|-------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------| | **核心功能** | 提供对共享资源的独占访问权,防止竞争条件的发生 | 实现线程间基于某种条件的等待/通知机制[^2] | | **适用范围** | 当仅需保证某一时间段内单一线程能操作某项资源时使用 | 多个线程依据具体逻辑判断是否进入下一步处理流程时采用 | | **典型应用场景** | 数据结构如链表节点增删改查等涉及全局状态变更的操作 | 生产者-消费者模式下协调不同角色的工作进度 | | **API特点** | `pthread_mutex_lock` 和 `pthread_mutex_unlock` | 结合互斥锁使用的 `pthread_cond_wait`, `pthread_cond_signal`, 或 `pthread_cond_broadcast` | #### 技术细节补充说明 尽管两者都属于同步原语家族成员之一,但它们解决的是不同类型的问题: - 对于简单的资源共享需求来说,单独依靠互斥锁已经足够完成任务; - 而对于更复杂的业务逻辑,则可能需要用到条件变量来精确控制何时解除另一个线程的休眠状态[^3]^. 另外值得注意的一点是,在调用任何有关条件变量的功能之前都需要先获取关联的那个互斥锁对象,这是因为这样可以有效避免虚假唤醒等问题发生[^4]. ```python import threading lock = threading.Lock() condition = threading.Condition(lock) with condition: while not some_condition(): condition.wait() # Notify other threads about the change. with condition: condition.notify_all() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值