多线程无法正确联接

Multi-thread can't join properly

本文关键字:多线程      更新时间:2023-10-16
#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_,这始终是正确的,在主线程中无法通过alive = false设置为False。

我尝试使alive成为全局变量,但仍然存在相同的错误。

你能给我一些建议吗?

可以更改

cov.wait(lk,[]{ return ready;});

to

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;
}

t1中,该函数不会经常测试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确保在条件变量上提供更多通知时,它才会唤醒。仅在此刻,它才能从等待状态退出,并且在处理后发现alivefalse

为了避免永远卡住,您可以更改代码并使用wait_for(),以便该功能可以按时检查是否仍应保持alive

#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;
}

整合建议,我将代码修改为上面。它按照我的期望输出。感谢所有的人提供建议,最好的问候。