本文转载https://blog.csdn.net/zhangxiao93/article/details/72677207
CountDownLatch
用于主线程等待工作线程完成工作,注意,这里与pthread_join
不一样:
pthread_join是只要线程active就会阻塞,线程结束就会返回.一般用于主线程回收工作线程.
CountDownLatch可以保证工作线程的任务执行完毕,主线程再对工作线程进行回收
1. 原理
CountDownLatch,本质上来说,是一个thread safe的计数器,用于主线程和工作线程的同步.
我所知道的用法有两种:
第一种:在初始化时,需要指定主线程需要等待的任务的个数(count),当工作线程完成 Task Callback后对计数器减1,而主线程通过wait()调用阻塞等待技术器减到0为止.
第二种:初始化计数器值为1,在程序结尾将创建一个线程执行countDown操作并wait()当程序执行到最后会阻塞直到计数器减为0,这可以保证线程池中的线程都start了线程池对象才完成析够,这是一个坑,我在实现ThreadPool的过程中遇到过
2. 实现
CountDownLatch是一个Thread Safe的Couter,它支持的方法主要是两个countDown()和wait()
countDown就是对counter原子的执行减1操作
wait就使用条件变量等待counter减到0然后notify.
3.代码
3.1 CountDownLatch.h
#ifndef __COUNTDOWNLATCH_H__
#define __COUNTDOWNLATCH_H__
#include "MutexLock.h"
#include "Condition.h"
class CountDownLatch : cl::NonCopy
{
public:
explicit CountDownLatch(int count)
: count_(count)
, mutex_()
, condition_(mutex_)
{
}
void wait()
{
LockGuard<Mutex> lock(mutex_);
while(count_ > 0)
{
condition_.wait();
}
}
void countDown()
{
LockGuard<Mutex> lock(mutex_);
--count_;
if(count_ == 0)
{
condition_.notify_all();
}
}
int getCount() const
{
LockGuard<Mutex> lock(mutex_);
return count_;
}
private:
int count_;
mutable Mutex mutex_;
Condition condition_;
};
#endif
————————————————
版权声明:本文为CSDN博主「NearXDU」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhangxiao93/article/details/72677207
使用相类似回环栅栏处理
explicit CyclicBarrier(int parties, CyclicBarrier::CyclicBarrierCallBack cb = NULL)
: parties_(parties)
, count_(parties)
, mutex_()
, condition_(mutex_)
, cb_(cb)
{
}
void reset()
{
LockGuard<Mutex> lock(mutex_);
nextGeneration();
}
int wait()
{
return dowait(false, 0);
}
/// Returns the number of parties required to trip this barrier.
int getParties() const
{
return parties_;
}
/// Returns the number of parties currently waiting at the barrier.
/// This method is primarily useful for debugging and assertions.
int getNumberWaiting()
{
LockGuard<Mutex> lock(mutex_);
return parties_ - count_;
}
private:
void nextGeneration()
{
// signal completion of last generation
condition_.notify_all();
// set up next generation
count_ = parties_;
}
int dowait(bool timed, int millisecond)
{
LockGuard<Mutex> lock(mutex_);
int index = --count_;
if (index == 0) // tripped
{
if(cb_)
{
cb_();
}
nextGeneration();
return 0;
}
// loop until tripped, broken, interrupted, or timed out
for (;;)
{
if (!timed)
condition_.wait();
else if (millisecond > 0)
condition_.timed_wait(millisecond);
return index;
}
}