我有两个主题。两者都被初始化,但第一个线程首先运行,而第二个线程等待第一个线程(call_once(flagEven1, [&](){cond2.wait(lock, [&](){return zeroEvenOddFlag == 1; }); });
)。在满足某个条件后,第一个线程唤醒第二个线程并进入休眠状态。
zeroEvenOddFlag = 0;
cond1.notify_all();
cond2.wait(lock, [&](){return zeroEvenOddFlag == 1; });
此过程交替进行,直到任务完成。现在,线程被锁定,我不知道发生了什么。线程在一起应该处理输入字符串并产生两个零和非零数字的字符串。我通过添加一个在线程(zeroEvenOddFlag
)之间共享的整数来纠正虚假唤醒。
#include <string>
#include <thread>
#include <future>
#include <cstdio>
#include <iostream>
#include <queue>
#include <condition_variable>
using namespace std;
mutex mu;
condition_variable cond1;
condition_variable cond2;
once_flag flagZero;
once_flag flagEven;
once_flag flagEven1;
int zeroEvenOddFlag = 0;
string printerFunc(queue<char>& input, int zeroEvenOdd, once_flag& flag){
string output = "";
function<void(string&)> f;
unique_lock<mutex> lock(mu);
call_once(flag, [&](){
if (zeroEvenOdd == 1){
f = [&](string& output){
int i = input.front() - '0';
if (i == 0){
output += to_string(i);
input.pop();
}
else {
zeroEvenOddFlag = 1;
cond2.notify_all();
cond1.wait(lock, [&](){return zeroEvenOddFlag == 0; });
}
};
}
else if (zeroEvenOdd == 2){
call_once(flagEven1, [&](){cond2.wait(lock, [&](){return zeroEvenOddFlag == 1; }); });
f = [&](string& output){
int i = input.front() - '0';
if (i != 0){
output += to_string(i);
input.pop();
}
else {
zeroEvenOddFlag = 0;
cond1.notify_all();
cond2.wait(lock, [&](){return zeroEvenOddFlag == 1; });
}
};
}
});
while(input.size()!=0){
f(output);
}
return output;
}
int _tmain(int argc, _TCHAR* argv[])
{
string input = "0102030";
queue<char> inputQueue;
for(char c : input){
inputQueue.push(c);
}
auto zeros = async(launch::async, printerFunc, ref(inputQueue), 1, ref(flagZero));
auto evens = async(launch::async, printerFunc, ref(inputQueue), 2, ref(flagEven));
string zerosString = zeros.get();
string evensString = evens.get();
cout << "these are the zeros " << zerosString << endl;
cout << "these are the evens " << evensString << endl;
this_thread::sleep_for(chrono::seconds(10));
return 0;
}
答案 0 :(得分:0)
您需要始终检查虚假的唤醒条件。 cond2.wait(lock, [&](){return zeroEvenOddFlag == 1; });
之类的使用有助于检查。此外,您在循环结束时遇到问题。哪个线程最终拥有互斥锁必须在它消耗队列的最后一位时释放它,以便其他线程可以释放完成。最终代码应如下所示:
#include <string>
#include <thread>
#include <future>
#include <cstdio>
#include <iostream>
#include <queue>
#include <condition_variable>
using namespace std;
mutex mu;
condition_variable cond1;
condition_variable cond2;
once_flag flagZero;
once_flag flagEven;
once_flag flagEven1;
int zeroEvenOddFlag = 0;
string printerFunc(queue<char>& input, int zeroEvenOdd, once_flag& flag){
string output = "";
function<void(string&)> f;
unique_lock<mutex> lock(mu);
call_once(flag, [&](){
if (zeroEvenOdd == 1){
f = [&](string& output){
int i = input.front() - '0';
if (i == 0){
output += to_string(i);
input.pop();
if (input.size() == 0){
zeroEvenOddFlag = 1;
cond2.notify_all();
}
}
else {
zeroEvenOddFlag = 1;
cond2.notify_all();
cond1.wait(lock, [&](){return zeroEvenOddFlag == 0; });
}
};
}
else if (zeroEvenOdd == 2){
call_once(flagEven1, [&](){cond2.wait(lock, [&](){return zeroEvenOddFlag == 1; }); });
f = [&](string& output){
int i = input.front() - '0';
if (i != 0){
output += to_string(i);
input.pop();
if (input.size() == 0){
zeroEvenOddFlag = 0;
cond1.notify_all();
}
}
else {
zeroEvenOddFlag = 0;
cond1.notify_all();
cond2.wait(lock, [&](){return zeroEvenOddFlag == 1; });
}
};
}
});
while(input.size()!=0){
f(output);
}
return output;
}
int _tmain(int argc, _TCHAR* argv[])
{
string input = "0102030";
queue<char> inputQueue;
for(char c : input){
inputQueue.push(c);
}
auto zeros = async(launch::async, printerFunc, ref(inputQueue), 1, ref(flagZero));
auto evens = async(launch::async, printerFunc, ref(inputQueue), 2, ref(flagEven));
string zerosString = zeros.get();
string evensString = evens.get();
cout << "these are the zeros " << zerosString << endl;
cout << "these are the evens " << evensString << endl;
this_thread::sleep_for(chrono::seconds(10));
return 0;
}