我正在学习 C++11 并发,我之前唯一的并发原语经验是在六年前的操作系统课上,所以如果可以的话,请保持温和。
在 C++11 中,我们可以写
std::mutex m;
std::condition_variable cv;
std::queue<int> q;
void producer_thread() {
std::unique_lock<std::mutex> lock(m);
q.push(42);
cv.notify_one();
}
void consumer_thread() {
std::unique_lock<std::mutex> lock(m);
while (q.empty()) {
cv.wait(lock);
}
q.pop();
}
这很好用,但是我对需要cv.wait
循环包装感到生气。我们需要循环的原因对我来说很清楚:
Consumer (inside wait()) Producer Vulture
release the lock
sleep until notified
acquire the lock
I MADE YOU A COOKIE
notify Consumer
release the lock
acquire the lock
NOM NOM NOM
release the lock
acquire the lock
return from wait()
HEY WHERE'S MY COOKIE I EATED IT
现在,我相信其中一件很酷的事情unique_lock
是我们可以传递它,对吧?因此,如果我们可以这样做,那将是非常优雅的:
Consumer (inside wait()) Producer
release the lock
sleep until notified
acquire the lock
I MADE YOU A COOKIE
notify and yield(passing the lock)
wake(receiving the lock)
return from wait()
YUM
release the lock
现在 Vulture 线程无法突袭,因为互斥锁从I MADE YOU A COOKIE
到一直保持锁定状态YUM
。另外,如果notify()
需要您传递锁,这是确保人们在调用之前实际锁定互斥锁的好方法notify()
(请参阅Signaling a condition variable (pthreads))。
我很确定 C++11 没有这个习语的任何标准实现。其历史原因是什么(仅仅是 pthreads 没有这样做吗?那么为什么会这样)?是否有技术原因导致冒险的 C++ 编码人员无法在标准 C++11 中实现这个习语,也许称之为my_better_condition_variable
?
我也有一种模糊的感觉,也许我正在重新发明信号量,但我对学校的记忆不够,不知道这是否准确。