多线程中 关于条件变量和互斥锁的疑惑(纯干货)

条件变量的执行过程(伪代码)

int pthread_cond_wait(&cond,&wait)
{  
  int ret = pthread_cond_wait_and unlock(&cond,&wait);//进入阻塞状态后解锁
  pthread_mutex_lock(&lock);//再去竞争锁
  return ret
}

条件变量为什么要搭配互斥锁

1 条件变量的改变一般是临界资源来完成的,那么修改临界资源首先应该加锁
而线程在条件不满足的情况下要阻塞,等待别人唤醒,
那么在阻塞后一定要把锁放开,等到合适的线程拿到锁去修改临界资源,否则会出现死锁

2 在线程被唤醒后第一件事也应该是争取拿到锁,恢复以前加锁的状态.

否则在执行条件变量成立后的代码也法保证其原子性

所以条件变量和锁是相辅相成的:

条件变量需要锁的保护
锁需要 条件变量成立后,后重新上锁

条件变量为什么要使用while循环判断,而不是if

首先我们应该了解,条件变量是用来阻塞或者唤醒线程的,

阻塞和唤醒是依靠信号机制来处理的,

条件变量中的条件是我们自己规定的,

也就是说当条件成立后,操作系统给阻塞进程发送信号,唤醒这个进程

那万一操作系统抽风了,随便给进程发送唤醒信号 (此时条件还没成立),

线程醒了之后就会在条件没成立的情况下执行之后的代码

这也是第一点 用if 不能保证bug信号的有效处理, 但是
while()
{
cond_wait(&cond,&mutex);
}
唤醒操作后如果再次竞争到锁,第一件事就是再次进入while 看条件是否成立 能有效杜绝bug信号

2.
生产消费者模型, 生产者生产一个产品,两个消费者 A和B 同时竞争这一个产品

假定是两个消费者都先后拿到锁,发现没有商品然后睡眠放锁
此时必定生产者得到锁,生产一个产品,然后退出
当用broadcat或者signal唤醒消费者时,
假设消费者A先拿到了锁 消费完产品之后退出
B后拿到锁, 因为是while 循环,又会执行一次判断 发现没有产品, 接着进入等待


如果 此时条件判断改成if 消费者b在wait被唤醒后 会直接执行接下来的消费语句

会发现生产者之只生产了1个产品,唤醒了两个消费者,两个消费者同时”消费”了一个产品
错误!
验证代码

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
int flag = 0;

void* product(void* msg)
{
    char* who = (char*) msg;
    pthread_mutex_lock(&mutex);
    flag = 1;
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&mutex);
    return NULL;
}
void* consume(void* msg)
{
    char* who = (char*) msg;
    pthread_mutex_lock(&mutex);
    while(flag == 0)
        pthread_cond_wait(&cond, &mutex);
    printf(" %s said : i got the flag\n", who);
    flag = 0;
    pthread_mutex_unlock(&mutex);
    return NULL;
}
int main()
{
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);
    pthread_t producter, consumer_1, consumer_2;
    pthread_create(&producter, NULL, product, "producter");
    pthread_create(&consumer_1, NULL, consume, "consumer_1");
    pthread_create(&consumer_2, NULL, consume, "consumer_2");
    pthread_join(producter, NULL);
    pthread_join(consumer_1, NULL);
    pthread_join(consumer_2, NULL);
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
}
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值