CountDownLatch::CountDownLatch(int count)
: mutex_(),
condition_(mutex_),
count_(count)
{
}
void CountDownLatch::wait()
{
MutexLockGuard lock(mutex_);
while (count_ > 0)
{
condition_.wait();
}
}
void CountDownLatch::countDown()
{
MutexLockGuard lock(mutex_);
--count_;
if (count_ == 0)
{
condition_.notifyAll();
}
}
int CountDownLatch::getCount() const
{
MutexLockGuard lock(mutex_);
return count_;
}
该类的功能在博客https://www.jianshu.com/p/e233bb37d2e6中有介绍,抄录下其中的概念部分:
countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。
是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。
该类的接口很简单,wait接口是通过调用条件变量的wait等待count的值变为0。countDown将count-1,并且在cout==0的时候唤醒等待的条件变量,这时候调用wait的程序就会被唤醒并继续执行。
使用muduo中的一个例子,说明其用法
在muduo的线程类实现中,用到了该类,在Thread的构造函数中,将之初始化为1,
Thread::Thread(ThreadFunc func, const string& n)
: started_(false),
joined_(false),
pthreadId_(0),
tid_(0),
func_(std::move(func)),
name_(n),
latch_(1)
{
setDefaultName();
}
latch_就是CountDownLatch类对象,在start接口中,
void Thread::start()
{
assert(!started_);
started_ = true;
// FIXME: move(func_)
detail::ThreadData* data = new detail::ThreadData(func_, name_, &tid_, &latch_);
if (pthread_create(&pthreadId_, NULL, &detail::startThread, data))
{
started_ = false;
delete data; // or no delete?
LOG_SYSFATAL << "Failed in pthread_create";
}
else
{
latch_.wait();
assert(tid_ > 0);
}
}
可以看到,在pthread_create创建一个线程后,会使用CountDownLatch类的wait接口,阻塞等待,等待的是什么呢?新创建的线程会执行如下程序:
void runInThread()
{
*tid_ = muduo::CurrentThread::tid();
tid_ = NULL;
latch_->countDown();
latch_ = NULL;
当执行到latch_->countDown时,就会唤醒调用wait的线程。所以这里就是确保新创建的线程已经开始执行了。在新的线程开始执行后再从start返回。