等待队列中为什么需要互斥锁?一个线程在等待时被唤醒后会做什么?安全队列的代码实现

同步

作用

让多个执行流在访问临界资源的时候是合理访问

条件变量及其接口

本质是:一个PCB等待队列
条件变量 = PCB等待队列 + 一堆接口
PCB等待队列:当线程发现资源不可用的时候,调用变量接口将自己放到PCB等待队列,等待被唤醒

条件变量的类型:pthread_cond_t

初始化

静态初始化
 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
动态初始化
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
cond:待要初始化的“条件变量”的变量
	一般情况下,传递一个pthread_cond_t类型变量的地址
attr:一般情况下直接给NULL,采用默认属性

等待接口

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
cond:条件变量
mutex:互斥锁
作用:如果一个执行流调用了该接口,就会将执行流对应的PCB放到参数cond的PCB等待队列当中

唤醒接口

int pthread_cond_signal(pthread_cond_t *cond);
作用:通知(唤醒)PCB等待队列当中的线程,如果被通知的线程接收到了,则从PCB等待队列当中出队操作,正常执行代码
注意:至少唤醒一个PCB等待队列当中的线程
int pthread_cond_broadcast(pthread_cond_t *cond);
作用:同signal一致
注意:唤醒所有PCB等待队列当中的线程

销毁接口

int pthread_cond_destroy(pthread_cond_t *cond);
销毁动态初始化的条件变量

代码实现

    1 #include <stdio.h>
    2 #include <unistd.h>
    3 #include <pthread.h>
    4 
    5 int g_bowl = 1;
    6 
    7 pthread_mutex_t g_lock;
    8 
    9 //eat
W> 10 void* MyThreadA(void* arg)
   11 {
   
   12   while(1)
   13   {
   
   14     pthread_mutex_lock(&g_lock);
W> 15     printf("i eat %d, i am %p\n", g_bowl, pthread_self());
   16     g_bowl--;
   17     pthread_mutex_unlock(&g_lock);
   18   }
   19   return NULL;
   20 }
   21 
   22 //make
W> 23 void* MyThreadB(void* arg)
   24 {
   
   25   while(1)
   26   {
   
   27     pthread_mutex_lock(&g_lock);
   28     g_bowl++;
W> 29     printf("i make %d, i am %p\n", g_bowl, pthread_self());
   30     pthread_mutex_unlock(&g_lock);
   31   }
   32   return NULL;
   33 }
   34 
   35 int main()
   36 {
   
   37   pthread_mutex_init(&g_lock, NULL);
   38   pthread_t tid_A, tid_B;
   39   pthread_create(&tid_A, NULL, MyThreadA, NULL);
   40   pthread_create(&tid_B, NULL, MyThreadB, NULL);
   41 
   42   pthread_join(tid_A, NULL);
   43   pthread_join(tid_B, NULL);
   44 
   45   pthread_mutex_destroy(&g_lock);  
   46   return 0;
   47 }

这是一个吃面和做面的代码,一个工作线程A代表吃面的人,一个工作线程B代表做面的人,运行一下
在这里插入图片描述
好家伙都吃到负数去了,修改一下

    1 #include <stdio.h>
    2 #include <unistd.h>
    3 #include <pthread.h>
    4 #include <stdlib.h>
    5 
    6 #define THREAD_NUM 1//创建一个宏,后边修改宏即可
    7 
    8 int g_bowl = 1;
    9 pthread_mutex_t g_lock;
   10 pthread_cond_t g_cond;//定义变量
   11 
   12 //eat
W> 13 void* MyThreadA(void* arg)
   14 {
   
   15   while(1)
   16   {
   
   17     pthread_mutex_lock(&g_lock);
   18     //加完锁后需要判断是否能够吃
   19     //没有面则等待,有则吃
   20     if(g_bowl < 1)//没有面的情况
   21     {
   
   22       //等待
   23       pthread_cond_wait(&g_cond, &g_lock);
   24     }
   25     //有面吃就打印
W> 26     printf("i eat %d, i am %p\n", g_bowl, pthread_self());
   27     g_bowl--;
   28     pthread_mutex_unlock(&g_lock);
   29     //吃完面后通知(唤醒)做面的人
   30     pthread_cond_signal(&g_cond);
   31   }
   32   return NULL;
   33 }
   34 
   35 //make
W> 36 void* MyThreadB(void* arg)
   37 {
   
   38   while(1)
   39   {
   
   40     pthread_mutex_lock(&g_lock);
   41     //加完锁后需要判断是否继续做
   42     //有面则等待,没面做面
   43     if(g_bowl >= 1)//有面的情况
   44     {
   
   45       //等待
   46       pthread_cond_wait(&g_cond, &g_lock);
   47     }
   48     //没有面进入下一步做面
   49     g_bowl++;
W> 50     printf("i make %d, i am %p\n", g_bowl, pthread_self());
   51     pthread_mutex_unlock(&g_lock);
   52     //通知吃面
   53     pthread_cond_signal(&g_cond);
   54   }
   55   return NULL;
   56 }
   57 
   58 int main()
   59 {
   
   60   pthread_mutex_init(&g_lock, NULL);
   61 
   62   pthread_cond_init(&g_cond, NULL);//初始化
   63 
   64   pthread_t tid_A[THREAD_NUM], tid_B[THREAD_NUM];
   65   for(int i = 0; i < THREAD_NUM; i++)
   66   {
   
   67     int ret = pthread_create(&tid_A[i], NULL, MyThreadA, NULL);
   68     if(ret < 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值