自己动手写线程池之锁的优化
2016-07-09 16:46
176 查看
问题描述
线程池将任务Task添加到工作队列中,该队列使用
STL List实现。每次添加任务的时候,都需要获取线程锁,然后操作队列。
template <typename Item> void ThreadQueue<Item>::Push(const Item &item) { { ThreadLocker::Locker lock(&_locker); _queue.push_back(item); } _locker.Signal(); }
问题来了,如何实现一个批量插入接口?
template <typename Item, typename Type> void ThreadQueue<Item, Type>::Push(const QueueType &queue) { int notify_cnt = 0; { ThreadLocker::Locker lock(&_locker); typename QueueType::const_iterator iter = queue.begin(); for ( ; iter != queue.end(); iter++) { _queue.push_back(*iter); notify_cnt += 1; } } for (int i = 0; i < notify_cnt; i++) { _locker.Signal(); } }
批量操作,需要记录添加item的数量,在添加完成之后,进行Signal,通知工作线程,有新的任务到来。但这非常不方便,在任务需要批量操作的时候,都需要计数器。换个思路,能不能将计数器搬到锁管理类内,在解锁的时候,自动进行通知呢?
/* 理想代码 */ template <typename Item, typename Type> void ThreadQueue<Item, Type>::Push(const QueueType &queue) { ThreadLocker::Locker lock(&_locker); typename QueueType::const_iterator iter = queue.begin(); for ( ; iter != queue.end(); iter++) { _queue.push_back(*iter); _locker.Notify(); } }
解决方法
在锁管理类ThreadLocker中,引入计数器
_notify_num。
Notify的时候,进行Signal操作,而仅仅是将计数器自增,在解锁的时候,进行实际操作。
/* 计数器自增 */ void ThreadLocker::Notify() { if (_notify_num != -1) { _notify_num += 1; } } /* 解锁操作 */ void ThreadLocker::UnLock() { _thread_mutex.UnLock(); NotifyImpl(); } /* 实际通知 */ void ThreadLocker::NotifyImpl() { if (_notify_num != 0) { if (_notify_num == -1) { BroadCast(); } else { for (int i = 0; i < _notify_num; i++) { Signal(); } } _notify_num = 0; } }
NOTE: 在获取锁的时候,notify_num必须清0,这样,在notify的时候,自增才有效。获取锁的时机不仅在Lock函数,还在Wait、TimeWait返回之后。
代码
https://github.com/spch2008/threadpool/blob/master/src/thread_locker.cpp
相关文章推荐
- 定价类型
- Android基础-4
- 流媒体文件应用常见问题解答
- 在一个应用程序,如何监测一个service内部的数据的变化
- Android基础-3
- 字典里有个数组,数组里面存放着几个不相同的字典模型怎么用MJExtension解析,
- 九度OJ-1166
- 单词的三个维度
- 程序的机器级表示 (4)
- 家庭动物园下载链接
- iOS 隐藏tabbar代码详解
- Java中assert关键字的实现
- 流式传输的实现途径
- 自己动手写线程池之线程池实现
- Android基础-2
- 7Cookie的使用
- 测试感受与总结
- Netty初学之一:简介-HellWord-讲解
- 视频
- Myeclipse 自动Debug sun.misc.URLClassPath解决办法