我这里有一个简单的例子:的std :: conditional_variable :: notify_all不唤醒所有线程
该项目可自从我尝试学习C++ 11个线程调用学术。 这里是对发生了什么事情的描述。
想象一下,一个真正的大std::string
有很多的的汇编源代码内像
MOV EBX,ECX; \ r \ nmov EAX,ECX; \ r \ n ....
Parse()
函数使用此字符串并通过标记行的开始和结束并将其作为string::const_iterators
保存到作业队列中来查找所有行位置。
之后,2个工作线程从队列中弹出此信息并将子字符串解析为IntStuction类对象。他们的push_back教学类的实例,导致进入std::vector<Instruction> result
这里是一个结构声明压阵号和一个子迭代器解析
struct JobItem {
int lineNumber;
string::const_iterator itStart;
string::const_iterator itEnd;
};
这是一个小记录器...
void ThreadLog(const char* log) {
writeMutex.lock();
cout << "Thr:" << this_thread::get_id() << " " << log << endl;
writeMutex.unlock();
}
这是共享数据:
queue<JobItem> que;
vector<Instruction> result;
下面是同步
condition_variable condVar;
mutex condMutex;
bool signaled = false;
mutex writeMutex;
bool done=false;
mutex resultMutex;
mutex queMutex;
每线程功能
void Func() {
unique_lock<mutex> condLock(condMutex);
ThreadLog("Waiting...");
while (!signaled) {
condVar.wait(condLock);
}
ThreadLog("Started");
while (!done) {
JobItem item;
queMutex.lock();
if (!que.empty()) {
item = que.front(); que.pop();
queMutex.unlock();
}
else {
queMutex.unlock();
break;
}
//if i comment the line below both threads wake up
auto instr = ParseInstruction(item.itStart, item.itEnd);
resultMutex.lock();
result.push_back(Instruction());
resultMutex.unlock();
}
管理的线程管理器功能的所有原语......在Func()
功能
vector<Instruction> Parser::Parse(const string& instructionStream){
thread thread1(Func);
thread thread2(Func);
auto it0 = instructionStream.cbegin();
auto it1 = it0;
int currentIndex = instructionStream.find("\r\n");
int oldIndex = 0;
this_thread::sleep_for(chrono::milliseconds(1000)); //experimental
int x = 0;
while (currentIndex != string::npos){
auto it0 = instructionStream.cbegin() + oldIndex;
auto it1 = instructionStream.cbegin() + currentIndex;
queMutex.lock();
que.push({ x,it0,it1 });
queMutex.unlock();
if (x == 20) {//fill the buffer a little bit before signal
signaled = true;
condVar.notify_all();
}
oldIndex = currentIndex + 2;
currentIndex = instructionStream.find("\r\n", oldIndex);
++x;
}
thread1.join();
thread2.join();
done = true;
return result;
}
问题出现。正如你所看到的,我在里面使用了一些日志记录。和日志说:
Output:
Thr:9928 Waiting...
Thr:8532 Waiting...
Thr:8532 Started
含义,主线程曾派notify_all()
给等待的线程后,只有其中一人居然醒了。 如果我在Func()
的内部注释掉ParseInstruction()
的呼叫,那么两个线程都会唤醒,否则只有一个线程会这样。 得到一些建议会很好。
你能提供一个[**最小**完整和可验证的例子](http://www.stackoverflow.com/help/mcve)吗? – Barry
对'signaled'的赋值不受'condMutex'保护,所以'Func'可能永远不会看到它。 –
你能更具体吗? – Antiusninja