我在理解条件变量及其与互斥锁的使用方面遇到了一些麻烦,我希望社区可以帮助我。请注意,我来自 win32 背景,所以我与 CRITICAL_SECTION、HANDLE、SetEvent、WaitForMultipleObject 等一起使用。
这是我第一次尝试使用 c++11 标准库进行并发,它是此处找到的程序示例的修改版本。
#include <condition_variable>
#include <mutex>
#include <algorithm>
#include <thread>
#include <queue>
#include <chrono>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
std::queue<unsigned int> nNumbers;
std::mutex mtxQueue;
std::condition_variable cvQueue;
bool m_bQueueLocked = false;
std::mutex mtxQuit;
std::condition_variable cvQuit;
bool m_bQuit = false;
std::thread thrQuit(
[&]()
{
using namespace std;
this_thread::sleep_for(chrono::seconds(7));
// set event by setting the bool variable to true
// then notifying via the condition variable
m_bQuit = true;
cvQuit.notify_all();
}
);
std::thread thrProducer(
[&]()
{
using namespace std;
int nNum = 0;
unique_lock<mutex> lock( mtxQuit );
while( ( ! m_bQuit ) &&
( cvQuit.wait_for( lock, chrono::milliseconds(10) ) == cv_status::timeout ) )
{
nNum ++;
unique_lock<mutex> qLock(mtxQueue);
cout << "Produced: " << nNum << "\n";
nNumbers.push( nNum );
}
}
);
std::thread thrConsumer(
[&]()
{
using namespace std;
unique_lock<mutex> lock( mtxQuit );
while( ( ! m_bQuit ) &&
( cvQuit.wait_for( lock, chrono::milliseconds(10) ) == cv_status::timeout ) )
{
unique_lock<mutex> qLock(mtxQueue);
if( nNumbers.size() > 0 )
{
cout << "Consumed: " << nNumbers.front() << "\n";
nNumbers.pop();
}
}
}
);
thrQuit.join();
thrProducer.join();
thrConsumer.join();
return 0;
}
关于这个的几个问题。
我读过“任何打算等待 std::condition_variable 的线程必须首先获取一个 std::unique_lock 。”
所以我有一个 {quit mutex, condition variable & bool} 来指示何时发出退出信号。生产者和消费者线程必须分别获取一个 std::unique_lock ,如下所示:
std::unique_lock<std::mutex> lock(m_mtxQuit);
这让我很困惑。这不会将退出互斥锁锁定在第一个线程中,从而阻塞第二个线程吗?如果这是真的,那么第一个线程如何释放锁,以便另一个线程可以开始?
另一个问题:如果我将 wait_for() 调用更改为等待零秒,则该线程将被饿死。有人可以解释吗?我希望它在执行 while 循环之前不会阻塞(我是否正确假设 no_timeout 是recv'd 而不是超时?)。
如何调用 wait_for() 并指定零时间,以便 wait_for() 调用不会阻塞,而只是检查条件并继续?
我也很想听听关于这个主题的好的参考资料。