zoukankan      html  css  js  c++  java
  • Linux组件封装之二:Condition

    本博文讨论Linux中的条件变量Condition的封装;

    条件变量Condition 主要描述的是 线程间 的同步,即协作关系

    Linux中的条件变量通常涉及以下几个函数:

    int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
    int pthread_cond_signal(pthread_cond_t *cond);
    int pthread_cond_broadcast(pthread_cond_t *cond);
    int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
    int pthread_cond_destroy(pthread_cond_t *cond);

    一、条件变量类(Condition):

     1 #ifndef CONDITION_H_
     2 #define CONDITION_H_
     3 
     4 #include "NonCopyable.h"
     5 #include "MutexLock.h"
     6 #include <pthread.h>
     7 
     8 class Condition:NonCopyable //私有继承
     9 {
    10     public:        
    11         Condition(MutexLock &mutex);
    12         ~Condition();
    13 
    14         void wait();//等待
    15         void signal();//发送信号
    16     private:
    17         pthread_cond_t cond_;
    18         MutexLock &mutex_; //wait函数的参数
    19 };
    20 
    21 Condition::Condition(MutexLock &mutex)
    22     :mutex_(mutex)
    23 {
    24     pthread_cond_init(&cond_, NULL);
    25 }
    26 
    27 Condition::~Condition()
    28 {
    29     pthread_cond_destroy(&cond_);
    30 }
    31 
    32 void Condition::wait()
    33 {
    34     pthread_mutex_t  lock = mutex_.getMutex(); 
    35     pthread_cond_wait(&cond_, &lock);
    36 }
    37 
    38 void Condition::signal()
    39 {
    40     pthread_cond_signal(&cond_);
    41 }
    42 #endif

    这里要注意几点:

    1)、wait必须在加锁的条件下方可使用;

    2)、signal函数 一次唤醒一个线程,通常用来通知资源可用

    3)、broadcast函数一次通知多个线程,用来通知状态的改变,滥用其,将会导致“惊群”问题;

    使用wait函数时,必须使用while 循环原因如下

    1、采用 if 语句,最多只能判断一次;

    2、为了描述方便,我们假设,这里有 5 个生产者(producer), 3 个消费者(consumer),缓冲区中最多能盛放 10 个产品;

    a)假设现在缓冲区中已经存在10 个产品,如果再用生产者A抢到这把锁,就会调用 wait函数, 将producer函数阻塞,并释放该锁,

    b)这时有一个consumer抢到 该锁,自然会消费一个产品,并释放该锁,这时产品数还有 9 个;

    c)由于抢锁是不排队的,因此有可能是除了 A 之外的 producer(假设为B) 抢到锁,由于缓冲区未满(9个),因此会生产一个产品,这时缓冲区已满;

    d)还是由于抢锁是不排队的,这时有可能 A 又重新获得该锁,采用if语句,由于if 只会判断一次, 而且也已执行过,故A生产者会生产一个产品,由于缓冲区已满,这时生产产品就已无处可放,造成溢出。

    e)若采用whilt循环, A 若获得该锁,则会先判断缓冲区的状态(是否已满),如果已满,则又会进入阻塞状态,不会造成溢出。

    3、为了防止broadcast的干扰:如果有且仅有一个资源,使用broadcast会唤醒所有等待的线程,那么多个线程被唤醒,但最终只有一个能拿到资源,这就是所谓的“惊群效应”。

  • 相关阅读:
    Web Application Penetration Testing Local File Inclusion (LFI) Testing Techniques
    [Reproduced works]MongoDB Unauthorized Access Vulnerability
    PHP build notes
    两个坑-Linux下Network-Manager有线未托管-DNS resolv.conf文件开机被清空
    OS命令注入中的空格
    Honeywords项目——检查密码是否被破解的一种简单方法
    如何判断自己的VPS是那种虚拟技术实现的
    reGeorg v1.0内网流量转发
    配置OWASP的ModSecurity规则
    python 2.6 与 2.4 区别
  • 原文地址:https://www.cnblogs.com/xfxu/p/4008693.html
Copyright © 2011-2022 走看看