简体   繁体   English

多线程无法正常加入

[英]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;
}

I just want to test the condition variable in multi-thread. 我只想在多线程中测试条件变量。 The code above is my test code. 上面的代码是我的测试代码。

the error is that the thread t1 can't join properly. 错误是线程t1无法正常连接。 I print the alive_ , it is always true, can't be set to false by alive = false in the main thread. 我打印alive_ ,它总是如此,不能通过主线程中的alive = false设置为false。

I try to make alive a global variable, but still the same error. 我试着让一个全局变量alive ,但仍然是同样的错误。

Can you give me some advice? 你能给我一些建议吗?

Can be changed 可以改变

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

to

cov.wait(lk,[&alive_]{ return ready || !alive_;});
if (!alive_)
    break;

And below alive_=false; 并且在alive_=false;之下alive_=false; add the line 添加线

cov.notify_one();

The complete code is as follows 完整的代码如下

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

In t1 the function doesn't constantly test alive . t1该函数不会持续测试alive You have designed it so that every loop starts with waiting on the condition variable. 您已经设计了它,以便每个循环都以等待条件变量开始。 It then go sleep and wakeup only when notified. 然后它会在通知时进入睡眠状态并唤醒。 Unfortunately, when main sets alive to false, the t1 thread is still in a waiting state. 不幸的是,当main将alive设置为false时,t1线程仍处于等待状态。

You can observe this easily: 您可以轻松地观察到:

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

It will wake up only if main would ensure one more notifification on the condition variable. 只有当main确保对条件变量进行更多通知时,它才会被唤醒。 Only at this moment would it exit from its waiting state, and after processing find out that alive is false . 只有在这一刻它才会退出等待状态,并在处理后发现alivefalse

To avoid being stuck forever, you could change your code and make use of wait_for() so that the function can check on time out if it should still stay alive . 为了避免永远陷入困境,您可以更改代码并使用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;
}

Integrating the advice, I modify my code to be above. 整合建议,我修改我的代码在上面。 It output as I expected. 它按我的预期输出。 Thanks for all the people provide the advice, best regards. 感谢所有人提供的建议,最好的问候。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM