面試的時候常常被問到互斥量,條件變量和信號量之間的問題。好比前幾天華爲面試就被問到互斥量和信號量的區別,說到互斥量也能夠使用一個二值信號量來實現,什麼狀況是隻能使用互斥量而不能使用信號量的。這個問題當時我只回答出一種狀況,想了解詳情的可自行百度。如面試官所說,信號量能夠實現互斥量,大部分狀況下也能夠實現條件變量。甚至使用信號量的實現遠比其餘實現更容易理解。然而不少時候使用信號量替換條件變量的可能會下降併發程序的性能。
下面是我本身實現的一個線程池的代碼:
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