Ostep 30 Condition Variables

除了锁之外,并发程序中另一个最重要的模式就是条件变量,与锁不同,条件变量用于解决线程间的同步问题。

条件变量的基本api

主要由2个方法就可以实现,

pthread_cond_wait(pthread_cond_tc, pthread_mutex_tm);

pthread_cond_signal(pthread_cond_t*c);

一个wait,用于进入阻塞状态等待,一个signal,用于唤醒等待的线程。

为什么需要等待和被唤醒?我们当然可以写一个while循环无限检查一个公共变量来达到效果,但是从锁的实现我们就可以看出,自旋是最消耗性能的做法,它只在一开始自旋有限次数时,通过线程切换成本的降低,来具备较好的性能。

消费者,生产者队列

这里主要使用一个例子,即如何通过wait和signal2个条件变量的原语,来实现一个经典模型:消费者生产者队列。

这边直接贴最终版的,并且倒着去解释一些关键点了,原文中是从一堆错误慢慢演进的。

cond_t empty, fill;
mutex_t mutex;
int count = 0;
int loops = 10;
void* producer(void* arg) {
    int i;
    for (i = 0; i < loops; i++) {
        Pthread_mutex_lock(&mutex);
        while (count == 1)
            Pthread_cond_wait(&empty, &mutex);
        put(i);
        Pthread_cond_signal(&fill);
        Pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

void* consumer(void* arg) {
    int i;
    for (i = 0; i < loops; i++) {
        Pthread_mutex_lock(&mutex);
        while (count == 0)
            Pthread_cond_wait(&fill, &mutex);
        int tmp = get();
        Pthread_cond_signal(&empty);
        Pthread_mutex_unlock(&mutex);
        printf("%d\n", tmp);
    }
    return NULL;
}

有以下几个要点:

为什么wait和signal要在锁里操作?

​ 这是因为判断count==0或者==1,本身也是一段临界代码,判断后再进入wait是存在并发风险的,所以要在锁中操作,否则可能出现在判断了==0后,马上被修改为1了,但是依旧进入了wait并且再也无法被唤醒。

为什么用while循环判断

在并发场景下,使用while循环判断总是好过if判断。这里涉及到条件变量中的2种语义:

Mesa Semantics:被唤醒的线程需要重新获取锁,并且重新检查条件。实现简单,效率高,是大多数系统的默认语义。

Hoare Semantics:被唤醒的线程立即获得锁,条件保证满足,实现复杂,效率低。

在实际编程中,特别是在使用Pthreads时,你通常会遇到Mesa语义,需要在被唤醒后重新检查条件。

所以,使用while循环其实是一种Mesa语义,因为在被唤醒后继续往下执行时,以消费者为例,线程在count==0时进入wait,在苏醒后,线程无法保证count==1的条件在苏醒后依然成立,即wait被signal后,无法确保count!=0,因为此时也可能存在其他线程修改了count,所以需要再次检查count的值,如果此时依旧不满足,那么继续进入wait。

实现Hoare语义就可以保证,但是就像上面说的,Hoare语义实现非常复杂,而且效率低下。

条件变量的广播

有一种广播式的条件变量,叫做covering condition,就是一次性唤醒所有wait这个条件变量的线程,可以降低复杂度,但是性能开销会比较大。

条件变量怎么实现?

总结

这章主要就介绍了条件变量的使用,并且举了个例子说明如何使用条件变量实现并发程序。

版权声明:除特殊说明,博客文章均为intotw原创,依据CC BY-SA 4.0许可证进行授权,转载请附上出处链接及本声明。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇