IPC组件的分装之条件变量(14)

本文详细介绍了CountDownLatch类的设计与实现,包括其在多线程间的同步作用,通过两个具体的示例程序展示了如何利用CountDownLatch来协调主线程与子线程的工作流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Condition类图

-------------------------------------------------------

                Condition

--------------------------

-mutex_:MutexLock& //不负责MutexLock的生命周期

-pcond:pthread_cond_t  //条件变量

--------------------------

<<create>>-condition(mutex:MutexLock&)

<<destroy>>-Condition

+wait():void  //等待函数

+waitForSeconds(seconds:int) : bool  //等待函数

+notify():void //信号函数

+notifyAll():void//信号函数

-------------------------------------------------------

Condition的头文件

// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)

#ifndef MUDUO_BASE_CONDITION_H
#define MUDUO_BASE_CONDITION_H

#include <muduo/base/Mutex.h>

#include <boost/noncopyable.hpp>
#include <pthread.h>

namespace muduo
{
/*
Condition 不负责Mutex的生命周期
**/
class Condition : boost::noncopyable //不可复制的
{
 public:
  explicit Condition(MutexLock& mutex)
    : mutex_(mutex)
  {
     //初始化条件变量
    pthread_cond_init(&pcond_, NULL);
  }

  ~Condition()
  {//释放条件变量
    pthread_cond_destroy(&pcond_);
  }

  void wait()
  {
    pthread_cond_wait(&pcond_, mutex_.getPthreadMutex());
  }

  // returns true if time out, false otherwise.
  bool waitForSeconds(int seconds);

  void notify()
  {//发送条件变量
    pthread_cond_signal(&pcond_);
  }

  void notifyAll()
  { //广播条件变量
    pthread_cond_broadcast(&pcond_);
  }

 private:
  MutexLock& mutex_;
  pthread_cond_t pcond_;
};

}
#endif  // MUDUO_BASE_CONDITION_H


condition的源代码

// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)

#include <muduo/base/Condition.h>

#include <errno.h>

// returns true if time out, false otherwise.
bool muduo::Condition::waitForSeconds(int seconds)
{
  struct timespec abstime;
  clock_gettime(CLOCK_REALTIME, &abstime);
  abstime.tv_sec += seconds;
  return ETIMEDOUT ==   (&pcond_, mutex_.getPthreadMutex(), &abstime);
}




CountDownLatch类图

---------------------------------------

-mutex_:MutexLock

-condition_:Condition

-count_: int

------------------------

<<create>>-CoutDownLatch(count:int)

+wait():void

+coutDown():void

+getCount():int

-------------------------------------------

既可以用于所有子线程等待主线程发起“起跑”

也可以用于主线程等待子线程初始化完毕才开始工作

-------------------------------------------


CountDownLatch头文件

// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)

#ifndef MUDUO_BASE_COUNTDOWNLATCH_H
#define MUDUO_BASE_COUNTDOWNLATCH_H

#include <muduo/base/Condition.h>
#include <muduo/base/Mutex.h>

#include <boost/noncopyable.hpp>
/*

**/
namespace muduo
{

class CountDownLatch : boost::noncopyable //不可复制
{
 public:

  explicit CountDownLatch(int count);

  void wait();

  void countDown();

  int getCount() const;

 private:
  mutable MutexLock mutex_; //mutable 可以改变的
  Condition condition_; //条件变量类 MutexLock mutex_会传递给condition_
  int count_; //计数器,主要用来协程处理 
};

}
#endif  // MUDUO_BASE_COUNTDOWNLATCH_H


CountDownLatch源文件

// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)

#include <muduo/base/CountDownLatch.h>

using namespace muduo;

CountDownLatch::CountDownLatch(int count) //使用计数器进行初始化
  : mutex_(),
    condition_(mutex_), //传递给condition类
    count_(count)
{
}
/*
等待线程,一直等到条件满足
*/
void CountDownLatch::wait()
{
  MutexLockGuard lock(mutex_);
  while (count_ > 0) { //等待,muduo 把count_ ==0 才是条件满足,这些我们自己在封装时,可以自己设定该值
    condition_.wait();
  }
}
/*
减少计算器,逼近条件满足,如果满足则唤醒 “睡眠的线程”
**/
void CountDownLatch::countDown()
{
  MutexLockGuard lock(mutex_);
  --count_; // 
  if (count_ == 0) {
    condition_.notifyAll();
  }
}
/*
获取计算器
**/
int CountDownLatch::getCount() const//正常时候下面变量的状态是不可以被改变的,
                                    //但是mutex被mutable修饰了,所以他的状态是可以被改变的,
                                    //而count_的状态就不可以被改变了
{
  MutexLockGuard lock(mutex_);
  return count_;
}







测试程序1 :

#include <muduo/base/CountDownLatch.h>
#include <muduo/base/Thread.h>

#include <boost/bind.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <string>
#include <stdio.h>

/*
该程序的主要功能是:
    主线程先创建3个线程,然后线程会等待主线程释放“计数器”,也就是cont_;
    主线程休眠3秒钟,然后发布命令(把count_设为0,然后唤醒上面的程序)。
**/

using namespace muduo;

class Test
{
 public:
  Test(int numThreads): latch_(1), //计算器初始化为1 
                        threads_(numThreads) //线程的个数
  { 
      //创建numthreads个线程,把他们放到容器threads_中
    for (int i = 0; i < numThreads; ++i)
    {
      char name[32];
      snprintf(name, sizeof name, "work thread %d", i);
      //创建线程,线程的回调函数为Test::threadFunc ,线程会阻塞在该函数中,一直等待count_ == 0 
      threads_.push_back(new muduo::Thread(boost::bind(&Test::threadFunc, this), muduo::string(name)));
    }
    //循环启动线程
    for_each(threads_.begin(), threads_.end(), boost::bind(&Thread::start, _1));
  }

  void run()
  { //发布命令,count_ -- = 0 
    latch_.countDown();
  }
    //等待线程
  void joinAll()
  {
    for_each(threads_.begin(), threads_.end(), boost::bind(&Thread::join, _1));
  }

 private:

  void threadFunc()
  {
     //等待count_ 满足条件
    latch_.wait();
    //成功后运行
    printf("tid=%d, %s started\n",
           CurrentThread::tid(),
           CurrentThread::name());



    printf("tid=%d, %s stopped\n",
           CurrentThread::tid(),
           CurrentThread::name());
  }

  CountDownLatch latch_; //协程
  boost::ptr_vector<Thread> threads_; //线程指针容器
};

int main()
{
    //
  printf("pid=%d, tid=%d\n", ::getpid(), CurrentThread::tid());
    //计算器被设置为   
  Test t(3);
  sleep(3);
  printf("pid=%d, tid=%d %s running ...\n", ::getpid(), CurrentThread::tid(), CurrentThread::name());
  t.run();
  t.joinAll();

  printf("number of created threads %d\n", Thread::numCreated());
}


测试程序2

#include <muduo/base/CountDownLatch.h>
#include <muduo/base/Thread.h>

#include <boost/bind.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <string>
#include <stdio.h>

/**
该程序的主要功能:
    主线程创建 3 个线程,协程变量为3 , 主线程阻塞,一直到3个线程依次 count_--,此时count_ ==0 , 主线程
    才会被唤醒。
    程序1是子线程等待主线程发布命令
    程序2是主线程等待子线程“准备好”了,才开始一起运行。

***/
using namespace muduo;

class Test
{
 public:
  Test(int numThreads)
    : latch_(numThreads),
      threads_(numThreads)
  {
    for (int i = 0; i < numThreads; ++i)
    {
      char name[32];
      snprintf(name, sizeof name, "work thread %d", i);
      threads_.push_back(new muduo::Thread(
            boost::bind(&Test::threadFunc, this), muduo::string(name)));
    }
    for_each(threads_.begin(), threads_.end(), boost::bind(&muduo::Thread::start, _1));
  }

  void wait()
  {
    latch_.wait();
  }

  void joinAll()
  {
    for_each(threads_.begin(), threads_.end(), boost::bind(&Thread::join, _1));
  }

 private:

  void threadFunc()
  {
    sleep(3);
    latch_.countDown();
    printf("tid=%d, %s started\n",
           CurrentThread::tid(),
           CurrentThread::name());



    printf("tid=%d, %s stopped\n",
           CurrentThread::tid(),
           CurrentThread::name());
  }

  CountDownLatch latch_;
  boost::ptr_vector<Thread> threads_;
};

int main()
{
  printf("pid=%d, tid=%d\n", ::getpid(), CurrentThread::tid());
  Test t(3);
  t.wait();
  printf("pid=%d, tid=%d %s running ...\n", ::getpid(), CurrentThread::tid(), CurrentThread::name());
  t.joinAll();

  printf("number of created threads %d\n", Thread::numCreated());
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值