多线程无法正常加入
Multi-thread can't join properly
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
using namespace std;
mutex m;
condition_variable cov;
bool ready = false;
bool processed = false;
void showNum(int &f_, atomic_bool &alive_)
{
while(alive_)
{
unique_lock<mutex> lk(m);
cov.wait(lk,[]{ return ready;});
f_++;
ready = false;
processed= true;
lk.unlock();
cout<<f_<<endl;
cov.notify_one();
}
}
int main() {
vector<int> va;
for (int i = 0; i < 10; ++i) {
va.push_back(i);
}
int f = 0;
atomic_bool alive{ true };
std::thread t1(showNum,ref(f),ref(alive));
auto sizeofVector = va.size();
for (int j = 0; j < sizeofVector; ++j) {
{
lock_guard<mutex> lk0(m);
f = va.back();
cout<<f<<" ";
ready = true;
}
cov.notify_one();
va.pop_back();
{
unique_lock<mutex> lk(m);
cov.wait(lk,[]{return processed;});
processed = false;
lk.unlock();
}
}
alive = false;
t1.join();
return 0;
}
我只是想在多线程中测试条件变量。
上面的代码是我的测试代码。
错误是线程 t1 无法正常加入。我打印 alive_
,它总是 true,不能被主线程中的 alive = false
设置为 false。
我尝试把alive
设为全局变量,还是一样的错误
你能给我一些建议吗?
在 t1
中,函数不会经常测试 alive
。您已将其设计为每个循环都从等待条件变量开始。然后只有在收到通知时才会进入睡眠和唤醒状态。不幸的是,当 main 将 alive 设置为 false 时,t1 线程仍处于等待状态。
你可以很容易地观察到这一点:
void showNum(int &f_, atomic_bool &alive_)
{
while(alive_)
{ cout<<"waiting..."<<endl;
unique_lock<mutex> lk(m);
cout<<"waiting more..."<<endl;
cov.wait(lk,[]{ return ready;}); ///<<<<< stuck here
cout<<"go..."<<endl;
f_++;
ready = false;
processed= true;
lk.unlock();
cout<<" sn:"<<f_<<endl;
cov.notify_one();
}
}
只有在main
确保条件变量再有一次通知时才会唤醒。只有此时才会退出等待状态,处理后发现 alive
是 false
。
为避免永远卡住,您可以更改代码并使用 wait_for()
,以便函数可以检查超时是否仍应停留在 alive
。
可以更改
cov.wait(lk,[]{ return ready;});
到
cov.wait(lk,[&alive_]{ return ready || !alive_;});
if (!alive_)
break;
在 alive_=false;
下面添加行
cov.notify_one();
完整代码如下
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
using namespace std;
mutex m;
condition_variable cov;
bool ready = false;
bool processed = false;
void showNum(int &f_, atomic_bool &alive_)
{
while(alive_)
{
unique_lock<mutex> lk(m);
cov.wait(lk,[&alive_]{return ready || !alive_;});
if (!alive_)
break;
f_++;
ready = false;
processed= true;
lk.unlock();
cout<<f_<<endl;
cov.notify_one();
}
}
int main() {
vector<int> va;
for (int i = 0; i < 10; ++i) {
va.push_back(i);
}
int f = 0;
atomic_bool alive{ true };
std::thread t1(showNum,ref(f),ref(alive));
auto sizeofVector = va.size();
for (int j = 0; j < sizeofVector; ++j) {
{
lock_guard<mutex> lk0(m);
f = va.back();
cout<<f<<" ";
ready = true;
}
cov.notify_one();
va.pop_back();
{
unique_lock<mutex> lk(m);
cov.wait(lk,[]{return processed;});
processed = false;
lk.unlock();
}
}
alive = false;
cov.notify_one();
t1.join();
return 0;
}
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <chrono>
using namespace std;
mutex m;
condition_variable cov;
bool ready = false;
bool processed = false;
atomic_bool alive{ true };
void showNum(int &f_, atomic_bool &alive_)
{
while(alive)
{
unique_lock<mutex> lk(m);
cov.wait(lk,[]{ return ready || !alive;});
if(!alive)
break;
f_++;
ready = false;
processed= true;
lk.unlock();
cout<<f_<<endl;
cov.notify_one();
}
}
int main() {
vector<int> va;
for (int i = 0; i < 10; ++i) {
va.push_back(i);
}
int f = 0;
std::thread t1(showNum,ref(f),ref(alive));
auto sizeofVector = va.size();
for (int j = 0; j < sizeofVector; ++j) {
{
lock_guard<mutex> lk0(m);
f = va.back();
cout<<f<<" ";
ready = true;
}
cov.notify_one();
va.pop_back();
{
unique_lock<mutex> lk(m);
cov.wait(lk,[]{return processed;});
processed = false;
lk.unlock();
}
}
alive = false;
cov.notify_one();
t1.join();
return 0;
}
结合建议,我修改了上面的代码。它按我的预期输出。
感谢所有提供建议的人,致以最诚挚的问候。
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
using namespace std;
mutex m;
condition_variable cov;
bool ready = false;
bool processed = false;
void showNum(int &f_, atomic_bool &alive_)
{
while(alive_)
{
unique_lock<mutex> lk(m);
cov.wait(lk,[]{ return ready;});
f_++;
ready = false;
processed= true;
lk.unlock();
cout<<f_<<endl;
cov.notify_one();
}
}
int main() {
vector<int> va;
for (int i = 0; i < 10; ++i) {
va.push_back(i);
}
int f = 0;
atomic_bool alive{ true };
std::thread t1(showNum,ref(f),ref(alive));
auto sizeofVector = va.size();
for (int j = 0; j < sizeofVector; ++j) {
{
lock_guard<mutex> lk0(m);
f = va.back();
cout<<f<<" ";
ready = true;
}
cov.notify_one();
va.pop_back();
{
unique_lock<mutex> lk(m);
cov.wait(lk,[]{return processed;});
processed = false;
lk.unlock();
}
}
alive = false;
t1.join();
return 0;
}
我只是想在多线程中测试条件变量。 上面的代码是我的测试代码。
错误是线程 t1 无法正常加入。我打印 alive_
,它总是 true,不能被主线程中的 alive = false
设置为 false。
我尝试把alive
设为全局变量,还是一样的错误
你能给我一些建议吗?
在 t1
中,函数不会经常测试 alive
。您已将其设计为每个循环都从等待条件变量开始。然后只有在收到通知时才会进入睡眠和唤醒状态。不幸的是,当 main 将 alive 设置为 false 时,t1 线程仍处于等待状态。
你可以很容易地观察到这一点:
void showNum(int &f_, atomic_bool &alive_)
{
while(alive_)
{ cout<<"waiting..."<<endl;
unique_lock<mutex> lk(m);
cout<<"waiting more..."<<endl;
cov.wait(lk,[]{ return ready;}); ///<<<<< stuck here
cout<<"go..."<<endl;
f_++;
ready = false;
processed= true;
lk.unlock();
cout<<" sn:"<<f_<<endl;
cov.notify_one();
}
}
只有在main
确保条件变量再有一次通知时才会唤醒。只有此时才会退出等待状态,处理后发现 alive
是 false
。
为避免永远卡住,您可以更改代码并使用 wait_for()
,以便函数可以检查超时是否仍应停留在 alive
。
可以更改
cov.wait(lk,[]{ return ready;});
到
cov.wait(lk,[&alive_]{ return ready || !alive_;});
if (!alive_)
break;
在 alive_=false;
下面添加行
cov.notify_one();
完整代码如下
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
using namespace std;
mutex m;
condition_variable cov;
bool ready = false;
bool processed = false;
void showNum(int &f_, atomic_bool &alive_)
{
while(alive_)
{
unique_lock<mutex> lk(m);
cov.wait(lk,[&alive_]{return ready || !alive_;});
if (!alive_)
break;
f_++;
ready = false;
processed= true;
lk.unlock();
cout<<f_<<endl;
cov.notify_one();
}
}
int main() {
vector<int> va;
for (int i = 0; i < 10; ++i) {
va.push_back(i);
}
int f = 0;
atomic_bool alive{ true };
std::thread t1(showNum,ref(f),ref(alive));
auto sizeofVector = va.size();
for (int j = 0; j < sizeofVector; ++j) {
{
lock_guard<mutex> lk0(m);
f = va.back();
cout<<f<<" ";
ready = true;
}
cov.notify_one();
va.pop_back();
{
unique_lock<mutex> lk(m);
cov.wait(lk,[]{return processed;});
processed = false;
lk.unlock();
}
}
alive = false;
cov.notify_one();
t1.join();
return 0;
}
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <chrono>
using namespace std;
mutex m;
condition_variable cov;
bool ready = false;
bool processed = false;
atomic_bool alive{ true };
void showNum(int &f_, atomic_bool &alive_)
{
while(alive)
{
unique_lock<mutex> lk(m);
cov.wait(lk,[]{ return ready || !alive;});
if(!alive)
break;
f_++;
ready = false;
processed= true;
lk.unlock();
cout<<f_<<endl;
cov.notify_one();
}
}
int main() {
vector<int> va;
for (int i = 0; i < 10; ++i) {
va.push_back(i);
}
int f = 0;
std::thread t1(showNum,ref(f),ref(alive));
auto sizeofVector = va.size();
for (int j = 0; j < sizeofVector; ++j) {
{
lock_guard<mutex> lk0(m);
f = va.back();
cout<<f<<" ";
ready = true;
}
cov.notify_one();
va.pop_back();
{
unique_lock<mutex> lk(m);
cov.wait(lk,[]{return processed;});
processed = false;
lk.unlock();
}
}
alive = false;
cov.notify_one();
t1.join();
return 0;
}
结合建议,我修改了上面的代码。它按我的预期输出。 感谢所有提供建议的人,致以最诚挚的问候。