muduo源码解析7-countdownlatch类
阅读原文时间:2023年07月09日阅读:1

countdownlatch

class countdownlatch:noncopyable
{
};

countdownlatch和mutex,condition一样,用于线程之间的同步,主要用于这样一种情况:

有一组线程,计算线程,IO线程1,IO线程2,

我们规定计算线程必须在所有的IO线程都结束后才能执行。

如果单纯使用mutex,计算线程可能比其他IO线程先抢到mutex,这不符合计算线程最后执行的要求。

但是可以使用条件变量来完成,当然条件变量不能单独使用,需要配套一个mutex,计算线程必须在符合条件(IO1,IO2都完成)时才能获得锁。

countdownlatch就是使用条件变量来完成的,可以初始化一个countdownlatch(2),让IO1和IO2先执行,此时

countdownlatch内部m_count值为2,计算线程向要请求锁,但是条件变量不允许,因此m_count>0,只有当IO1和IO2都完成并对m_count--后,计算线程被唤醒,发现m_count==0才可以执行。

private:
mutable mutexlock m_mutex;
condition m_cond;
int m_count;

分别表示:互斥锁mutex,条件变量condition和执行线程计数count

public:
countdownlatch(int count):m_mutex(),m_cond(m_mutex),m_count(count){}

//我们要同步的那一个线程,要执行时必须先wait,只有先决线程全结束后才可以执行  
void wait()  
{  
    mutexlockguard mlg(m\_mutex);  
    while(m\_count>)  
        m\_cond.wait();  
}  
//先决线程执行完毕,让引用计数--  
void countDown()  
{  
    mutexlockguard mlg(m\_mutex);  
    m\_count--;  
    if(m\_count==)  
        m\_cond.notifyAll();  
}  
//返回先决线程即引用计数的数量  
int getCount() const  
{  
    mutexlockguard mlg(m\_mutex);  
    return m\_count;  
}

使用countdownlatch来测试上面的IO线程和计算线程同步的例子

#include"base/mutex.h"
#include"base/condition.h"
#include"base/countdownlatch.h"
#include
#include
#include
#include

namespace mymuduo{
namespace currentthread {

void cacheTid()
{
}
}
}

//初始化m_count为2,表示有两个先决线程IO1和IO2
mymuduo::countdownlatch cdl();

void IOThread()
{
//IO… 2s
std::this_thread::sleep_for(std::chrono::milliseconds());
std::cout<<"IO completed…\n";
cdl.countDown();
}

void computeThread()
{
//等待IO1和IO2完成后才能执行
cdl.wait();
std::cout<<"computing…\n";
}

int main()
{
std::thread t1,t2,t3;
t1=std::thread(computeThread);
t2=std::thread(IOThread);
t3=std::thread(IOThread);

t1.join();t2.join();t3.join();

}

计算结果:

不用想,computing…肯定在最后出现

IO completed…
IO completed…
computing…