C++ 尝试使用条件变量在线程之间切换

C++ 尝试使用条件变量在线程之间切换,c++,multithreading,C++,Multithreading,我有两条线。两者都会初始化,但第一个线程首先运行,而第二个线程等待第一个线程(调用_一次(flagEven1,[&](){cond2.wait(lock,[&](){return zeroEvenOddFlag==1;});});)。满足某个条件后,第一个线程唤醒第二个线程并进入睡眠状态 zeroEvenOddFlag = 0; cond1.notify_all(); cond2.wait(lock,

我有两条线。两者都会初始化,但第一个线程首先运行,而第二个线程等待第一个线程(
调用_一次(flagEven1,[&](){cond2.wait(lock,[&](){return zeroEvenOddFlag==1;});});
)。满足某个条件后,第一个线程唤醒第二个线程并进入睡眠状态

                zeroEvenOddFlag = 0;
                cond1.notify_all();
                cond2.wait(lock, [&](){return zeroEvenOddFlag == 1; });
此过程交替进行,直到任务完成。现在线程被锁定了,我不知道发生了什么。这些线程一起处理输入字符串,并生成两个由零和非零数字组成的字符串。我通过添加线程之间共享的整数(
zeroEvenOddFlag
)纠正了虚假唤醒

#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
互斥mu;
条件变量cond1;
条件变量cond2;
一次为零;
一次!;
一次1;
int zeroEvenOddFlag=0;
字符串printerFunc(队列和输入,int zeroEvenOdd,once_标志和标志){
字符串输出=”;
函数f;
唯一锁(mu);
调用_一次(标志,[&](){
if(zeroEvenOdd==1){
f=[&](字符串和输出){
int i=input.front()-“0”;
如果(i==0){
输出+=至_字符串(i);
input.pop();
}
否则{
zeroEvenOddFlag=1;
条件2.通知所有人();
cond1.wait(lock,[&](){return zeroEvenOddFlag==0;});
}
};
}
else if(zeroEvenOdd==2){
调用_一次(flagEven1,[&](){cond2.wait(lock,[&](){return zeroEvenOddFlag==1;});});
f=[&](字符串和输出){
int i=input.front()-“0”;
如果(i!=0){
输出+=至_字符串(i);
input.pop();
}
否则{
zeroEvenOddFlag=0;
条件1.通知所有人();
cond2.wait(lock,[&](){return zeroEvenOddFlag==1;});
}
};
}
});
while(input.size()!=0){
f(产出);
}
返回输出;
}
int _tmain(int argc,_TCHAR*argv[]
{
字符串输入=“0102030”;
队列输入队列;
for(字符c:输入){
push(c);
}
auto zeros=async(启动::async,printerFunc,ref(inputQueue),1,ref(flagZero));
auto-evens=async(启动::async,printerFunc,ref(inputQueue),2,ref(flagEven));
字符串zerosString=zeros.get();
字符串evensString=evens.get();

cout您需要始终检查虚假唤醒条件。使用
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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
互斥mu;
条件变量cond1;
条件变量cond2;
一次为零;
一次!;
一次1;
int zeroEvenOddFlag=0;
字符串printerFunc(队列和输入,int zeroEvenOdd,once_标志和标志){
字符串输出=”;
函数f;
唯一锁(mu);
调用_一次(标志,[&](){
if(zeroEvenOdd==1){
f=[&](字符串和输出){
int i=input.front()-“0”;
如果(i==0){
输出+=至_字符串(i);
input.pop();
if(input.size()==0){
zeroEvenOddFlag=1;
条件2.通知所有人();
}
}
否则{
zeroEvenOddFlag=1;
条件2.通知所有人();
cond1.wait(lock,[&](){return zeroEvenOddFlag==0;});
}
};
}
else if(zeroEvenOdd==2){
调用_一次(flagEven1,[&](){cond2.wait(lock,[&](){return zeroEvenOddFlag==1;});});
f=[&](字符串和输出){
int i=input.front()-“0”;
如果(i!=0){
输出+=至_字符串(i);
input.pop();
if(input.size()==0){
zeroEvenOddFlag=0;
条件1.通知所有人();
}
}
否则{
zeroEvenOddFlag=0;
条件1.通知所有人();
cond2.wait(lock,[&](){return zeroEvenOddFlag==1;});
}
};
}
});
while(input.size()!=0){
f(产出);
}
返回输出;
}
int _tmain(int argc,_TCHAR*argv[]
{
字符串输入=“0102030”;
队列输入队列;
for(字符c:输入){
push(c);
}
auto zeros=async(启动::async,printerFunc,ref(inputQueue),1,ref(flagZero));
auto-evens=async(启动::async,printerFunc,ref(inputQueue),2,ref(flagEven));
字符串zerosString=zeros.get();
字符串evensString=evens.get();

cout您需要始终检查虚假唤醒条件。使用
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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
互斥mu;
条件变量cond1;