面试的时候常常被问到互斥量,条件变量和信号量之间的问题。好比前几天华为面试就被问到互斥量和信号量的区别,说到互斥量也能够使用一个二值信号量来实现,什么状况是只能使用互斥量而不能使用信号量的。这个问题当时我只回答出一种状况,想了解详情的可自行百度。如面试官所说,信号量能够实现互斥量,大部分状况下也能够实现条件变量。甚至使用信号量的实现远比其余实现更容易理解。然而不少时候使用信号量替换条件变量的可能会下降并发程序的性能。
下面是我本身实现的一个线程池的代码:
github地址
这个线程池内部维护一个同步队列,同步队列实现了阻塞的pop和push接口。当队列为空的时候,在一个_emptyCond条件变量上等待;当队列满的时候,在一个_fullCond条件变量上等待。
核心代码以下:git
template<typename T>
T SyncQueue<T>::pop() {
bool wakePush = false;
T t;
{
ScopedLocker lock(_qMutex);
wakePush = (_q.size() == _capacity);
if (_q.empty()) {
pthread_cond_wait(&_emptyCond, &_qMutex);
}
wakePush |= (_q.size() == _capacity);
if (!_q.empty()) {
t = _q.front();
_q.pop_front();
}
}
if (wakePush) {
pthread_cond_broadcast(&_fullCond);
}
return t;
}github
template <typename T>
void SyncQueue<T>::push(T t) {
{
ScopedLocker lock(_qMutex);
while (_q.size() == _capacity) {
pthread_cond_wait(&_fullCond, &_qMutex);
}
_q.push_back(t);
}
pthread_cond_signal(&_emptyCond);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
使用这个线程池跑测试程序时,CPU的平均使用率为93%。面试
如今改成使用信号量的进行同步的队列,核心代码以下(git项目中的feature/semaphore分支):并发
template<typename T>
T SyncQueue<T>::pop() {
bool wakePush = false;
T t;
{
ScopedLocker lock(_qMutex);
wakePush = (_q.size() == _capacity);
if (_q.empty()) {
pthread_cond_wait(&_emptyCond, &_qMutex);
}
wakePush |= (_q.size() == _capacity);
if (!_q.empty()) {
t = _q.front();
_q.pop_front();
}
}
if (wakePush) {
pthread_cond_broadcast(&_fullCond);
}
return t;
}性能
template <typename T>
void SyncQueue<T>::push(T t) {
{
ScopedLocker lock(_qMutex);
while (_q.size() == _capacity) {
pthread_cond_wait(&_fullCond, &_qMutex);
}
_q.push_back(t);
}
pthread_cond_signal(&_emptyCond);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
运行一样的测试程序,CPU占用率只有83%,比使用条件变量的状况低了将近10%。测试
注:上述数据是使用top命令观察的结果,精确度有待论证,具体数据以实测为准。
---------------------
做者:Kylin_he
来源:CSDN
原文:https://blog.csdn.net/hekailing/article/details/48601809
版权声明:本文为博主原创文章,转载请附上博文连接!.net