pthread_cond_signal惊群现象

1.如下代码所示:

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

pthread_mutex_t count_lock;
pthread_cond_t count_ready;
int count;

void *decrement_count(void *arg)
{
        while(1)
        {
                pthread_mutex_lock(&count_lock);
                printf("decrement:waiting\n");
                /*等待满足条件,期间互斥量仍然可用*/
                //      while (count == 0)
                pthread_cond_wait(&count_ready, &count_lock);
                printf("decrement:count = %d\n",  count);
                if (count == 0)
                {
                        printf("exit count:%d\n",count);
                        exit(1);
                }
                count = 0;
                pthread_mutex_unlock(&count_lock);
        }
        pthread_exit(NULL);
}
void *increment_count(void *arg)
{
        while(1)
        {
                pthread_mutex_lock(&count_lock);
//              printf("increment:running\n");
                count = 1;
                /*通知线程条件已满足*/
//              printf("increment:count = %d\n",  count);
                pthread_cond_signal(&count_ready);
                pthread_mutex_unlock(&count_lock);
        }
        pthread_exit(NULL);
}

int main()
{
        pthread_t tid1,tid2,tid3;
        count=0;
        pthread_mutex_init(&count_lock, NULL);
        pthread_cond_init(&count_ready, NULL);

        pthread_create(&tid1, NULL, decrement_count, NULL);
        sleep(3);
        pthread_create(&tid3, NULL, decrement_count, NULL);
        sleep(3);
        pthread_create(&tid2, NULL, increment_count, NULL);
        /*等待decrement退出*/
        pthread_join(tid2, NULL);
        printf("decrement quit\n");
        pthread_join(tid3, NULL);
        pthread_join(tid1, NULL);
        return 0;
}

g++ -g thread-cond.cpp -lpthread -o test 编译出test程序。

然后运行,可见程序

decrement:waiting
decrement:waiting
decrement:count = 1
decrement:waiting
decrement:count = 0
exit count:0

最后退出了,为什么?

如果把tid1,tid2,tid3表示为每个线程获得互斥锁,那么这种情况的发生说明tid1和tid3顺序获得锁执行了(顺序也可能为tid3和tid1).

单从pthread_cond_signal函数的定义上看,如果严格的只发一个"信号"给指定一个线程,这种情况是绝对不可能发生的。

因为函数中pthread_cond_wait的返回代表了此线程接受到“信号”(pthread_cond_wait执行包括1.解锁2.wait3.获得锁4.返回)

只有一个原因能解释:pthread_cond_signal一次唤醒了2个wait线程,第1个获得锁的线程把count置为0,第2个线程发现count=0直接exit,

pthread_cond_signal发生了惊群现象。

怎么预防:

       while (count == 0)
          pthread_cond_wait(&count_ready, &count_lock);

在wait返回后加一个while来判断“条件”是否满足要求。
时间: 2024-10-08 18:22:17

pthread_cond_signal惊群现象的相关文章

Redis 利用锁机制来防止缓存过期产生的惊群现象-转载自 http://my.oschina.net/u/1156660/blog/360552

首先,所谓的缓存过期引起的“惊群”现象是指,在大并发情况下,我们通常会用缓存来给数据库分压,但是会有这么一种情况发生,那就是在一定时间 内生成大量的缓存,然后当缓存到期之后又有大量的缓存失效,导致后端数据库的压力突然增大,这种现象就可以称为“缓存过期产生的惊群现象”! 以下代码的思路,就是利用“锁机制”来防止惊群现象.先看代码: class KomaRedis{ private $redis; //redis对象 private static $_instance = null; private

Nginx如何解决“惊群”现象

首先解释下什么是"惊群"现象:如果多个工作进程同时拥有某个监听套接口,那么一旦该套接口出现某客户端请求,此时就将引发所有拥有该套接口的工作进程去争抢这个请求,能争抢到的肯定只有某一个工作进程,而其他工作进程注定要无功而返,这种现象即为"惊群". Nginx解决这种"惊群"现象使用的是负载均衡的策略,接下来先结合Nginx的源码详细介绍下Nginx的这种负载均衡策略. 首先是Nginx如何开启负载均衡策略:当然运行的Nginx要是多进程模型,并且工

Nginx中的惊群现象解决方法

*什么是惊群现象?Nginx中用了什么方法来避免这种问题的发生?本篇就解决这两个问题...→_→* 惊群现象的定义与危害 在Nginx中,每一个worker进程都是由master进程fork出来的.master进程创建socket后进行listen.bind操作,fork出来的worker继承了socket,调用accpet开始监听等待网络连接 如果这时有多个worker进程都在等待事件的发生.当事件发生时,这些worker进程被同时唤醒,但最终只有一个worker进程可以处理事件成功,其他的w

2、惊群现象

参考文献有 1:https://blog.csdn.net/russell_tao/article/details/7204260 2:https://www.jianshu.com/p/8f362e943e56 什么是“惊群”? 多线程/多进程(linux下线程进程也没多大区别)等待同一个socket事件,当这个事件发生时,这些线程/进程被同时唤醒,就是惊群.可以想见,效率很低下,许多进程被内核重新调度唤醒,同时去响应这一个事件,当然只有一个进程能处理事件成功,其他的进程在处理该事件失败后重新

Accept 惊群现象测试perl脚本

$uname -a Linux debian-11-34 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt9-3~deb8u1 (2015-04-24) x86_64 GNU/Linux 经过测试Debina 8.0 已经解决了Aceept thundering herd https://gist.github.com/kazuho/10436253 # 1) run this script with either "accept" or "se

惊群问题

惊群问题 惊群问题是由于系统中有多个进程在等待同一个资源,当资源可用的时候,系统会唤醒所有或部分处于休眠状态的进程去争抢资源,但是最终只会有一个进程能够成功的响应请求并获得资源,但在这个过程中由于系统要对全部的进程唤醒,导致了需要对这些进程进行不必要的切换,从而会产生系统资源的浪费. 这种情况一般是accept或epoll_create在子进程中处于监听状态,也就是先创建子进程或者子线程然后调用accept或epoll_create阻塞监听的时候发生-,然而在先调用accept阻塞和先创建epo

linux 惊群问题

1. 结论 对于惊群的资料,网上特别多,良莠不齐,也不全面.看的时候,有的资料说,惊群已经解决了,有的资料说,惊群还没解决.. 哪个才是对的?!  一怒之下,在研究各种公开资料的基础上,特意查对了linux源码,总结了此文.希望对有需要的人略有帮助,希望各位大神轻拍,如有错漏,不吝指教,感激不尽.([email protected]) 先说结论吧: 1. Linux多进程accept系统调用的惊群问题(注意,这里没有使用select.epoll等事件机制),在linux 2.6版本之前的版本存在

Linux网络编程“惊群”问题总结

1.前言 我从事Linux系统下网络开发将近4年了,经常还是遇到一些问题,只是知其然而不知其所以然,有时候和其他人交流,搞得非常尴尬.如今计算机都是多核了,网络编程框架也逐步丰富多了,我所知道的有多进程.多线程.异步事件驱动常用的三种模型.最经典的模型就是Nginx中所用的Master-Worker多进程异步驱动模型.今天和大家一起讨论一下网络开发中遇到的“惊群”现象.之前只是听说过这个现象,网上查资料也了解了基本概念,在实际的工作中还真没有遇到过.今天周末,结合自己的理解和网上的资料,彻底将“

accept与epoll惊群 转载

今天打开 OneNote,发现里面躺着一篇很久以前写的笔记,现在将它贴出来. 1. 什么叫惊群现象 首先,我们看看维基百科对惊群的定义: The thundering herd problem occurs when a large number of processes waiting for an event are awoken when that event occurs, but only one process is able to proceed at a time. After