zoukankan      html  css  js  c++  java
  • Linux组件封装(二) 条件变量Condition的封装

    声明代码如下:

     1 #ifndef CONDITION_H
     2 #define CONDITION_H
     3 
     4 #include <pthread.h>
     5 #include "NonCopyable.h"
     6 
     7 class MutexLock;
     8 
     9 
    10 class Condition : NonCopyable
    11 {
    12 public:
    13     Condition(MutexLock &mutex);
    14     ~Condition();
    15 
    16     void wait();
    17     void notify();
    18     void notifyAll();
    19 private:
    20     pthread_cond_t _cond;
    21     MutexLock &_mutex;
    22 };
    23 
    24 #endif
    View Code

    需要注意:

    1.wait必须在加锁条件下调用

    2.notify一次唤醒一个线程,通常用来通知资源可用

    3.notifyAll一次通知多个线程,通常用来通知状态的变化。滥用broadcast会导致"惊群"问题。

    使用wait必须采用while判断,原因在于:

    1.如果采用if,最多判断一次

    2.线程A等待数据,阻塞在full上,那么当另一个线程放入产品时,通知A去拿数据,此时另一个线程B抢到锁,直接进入临界区,取走资源。A重新抢到锁,(因为采用的是if,所以不会判断第二次)进去临界区时,已经没有资源。

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

    cpp代码实现如下:

     1 #include "Condition.h"
     2 #include "MutexLock.h"
     3 #include <assert.h>
     4 
     5 Condition::Condition(MutexLock &mutex)
     6     :_mutex(mutex)
     7 {
     8     TINY_CHECK(!pthread_cond_init(&_cond, NULL));
     9 }
    10 
    11 Condition::~Condition()
    12 {
    13     TINY_CHECK(!pthread_cond_destroy(&_cond));
    14 }
    15 
    16 void Condition::wait()
    17 {
    18     assert(_mutex.isLocked());
    19     TINY_CHECK(!pthread_cond_wait(&_cond, _mutex.getMutexPtr()));
    20     _mutex.restoreMutexStatus();
    21 }
    22 
    23 void Condition::notify()
    24 {
    25     TINY_CHECK(!pthread_cond_signal(&_cond));
    26 }
    27 
    28 void Condition::notifyAll()
    29 {
    30     TINY_CHECK(!pthread_cond_broadcast(&_cond));
    31 }
    View Code
  • 相关阅读:
    redis线程模型
    同步容器和并发容器
    200+面试题
    redis pipeline
    redis事务和脚本
    redis事务
    redis优缺点
    redis持久化策略
    Redis为什么要把所有数据放到内存中?
    redis的过期策略以及内存淘汰机制
  • 原文地址:https://www.cnblogs.com/gjn135120/p/4008570.html
Copyright © 2011-2022 走看看