Zeromq 源码全解析(3)

本文深入探讨ZMQ的任务分发设计,包括经典的线程池及其加锁问题,以及ZMQ如何通过单向加锁线程池和MailBox结构优化线程安全,避免资源抢占,实现高效的任务调度。ZMQ的MailBox存放命令结构,确保对象操作在单线程中执行,解决了跨线程调用的线程安全问题,并在对象分配时考虑了负载均衡。
摘要由CSDN通过智能技术生成

ZMQ任务分发设计

经典的线程池

经典的线程池多数是抢占式

在主线程上有个任务池,当有任务进入时,唤醒一个线程进行任务执行,以下是一个简单线程池的代码

//首先是一个线程数据,用来控制线程的
struct threadData {
    std::mutex mtx_;                            //互斥量
    std::condition_variable cond_;              //条件变量
    bool is_shutdown_ = false;                  //是否关机
    std::queue<std::function<void()>> tasks_;   //具体执行任务
};

class ThreadPool {
public:
    ThreadPool(size_t thread_cnt_):m_data(new threadData){
        //创建指定数量的线程
        for(size_t _i = 0 ; _i <thread_cnt_;_i++){
            std::thread([this](){
                //先进行上锁操作
                std::unique_lock<std::mutex> _lk(m_data->mtx_);
                for(;;){
                    //判断当前任务池中是否有任务
                    if(!m_data->tasks_.empty()){
                        //如果任务队列中有任务,则拿出任务执行
                        auto _func = std::move(m_data->tasks_.front());
                        //将取出的任务弹出
                        m_data->tasks_.pop();
                        //解锁
                        _lk.unlock();
                        //任务执行
                        _func();
                        //上锁
                        _lk.lock();
                    }else if(m_data->is_shutdown_){
                        //如果判断到关机信号,则直接退出
                        break;
                    }else{
                        //等待条件变量唤醒
                        m_data->cond_.wait(_lk);
                    }
                }
            }).detach();//从主线程中分离
        }
    }
    template<class TASK>
    void execute(TASK&& task_){
        //先上锁
        std::lock_guard<std::mutex> _lk(m_data->mtx_);
        //放入任务
        m_data->tasks_.emplace(std::forward<TASK>(task_));
        //唤醒一个线程
        m_data->cond_.notify_one();
    }

    ~ThreadPool(){
        //先上锁
        if(m_data){
            {
                std::lock_guard<std::mutex> _lk(m_data->mtx_);
                m_data->is_shutdown_ = true;
            }
            m_data->cond_.notify_all();
        }

    }
private:
    std::shared_ptr<threadData> m_data;
};

task_pool
task_a
task_b
task_c
Thread_a
Thread_b
Thread_c

用流程图来描述线程池的任务执行框架,可以明显发现,a,b,c线程可能会对task_pool进行同时访问,这个时候解决办法就是对task_pool进行加锁处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值