У меня возникли проблемы с пониманием переменных состояния и их использованием с помощью мьютексов, я надеюсь, что сообщество может мне помочь. Обратите внимание: я пришел из фона win32, поэтому я использую CRITICAL_SECTION, HANDLE, SetEvent, WaitForMultipleObject и т.д.
Здесь моя первая попытка в concurrency с использованием стандартной библиотеки С++ 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;
}
A Несколько вопросов об этом.
Я читал, что "любой поток, который намеревается ждать на std:: condition_variable, должен сначала получить std:: unique_lock."
Таким образом, у меня есть {quit mutex, condition variable и bool}, чтобы указать, когда было отправлено сообщение quit. Потребители и потребители должны каждый получить std:: unique_lock так:
std::unique_lock<std::mutex> lock(m_mtxQuit);
Это меня сбивает с толку. Разве это не блокирует мьютекс quit в первом потоке, тем самым блокируя второй? И если это правда, то как первый поток освобождает блокировку, чтобы начать другой поток?
Другой вопрос: если я изменил вызов wait_for(), чтобы подождать нулевые секунды, этот поток будет голоден. Может кто-нибудь объяснить? Я ожидаю, что он не будет блокироваться перед выполнением цикла while (правильно ли я предполагаю, что no_timeout recv'd вместо таймаута?).
Как я могу вызвать wait_for() и указать нулевое время, так что вызов wait_for() не блокируется, вместо этого он просто проверяет условие и продолжает?
Мне также будет интересно услышать о хороших ссылках на эту тему.