Search code examples
c++multithreadingcondition-variable

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. I print the alive_, it is always true, can't be set to false by alive = false in the main thread.

I try to make alive a global variable, but still the same error.

Can you give me some advice?


Solution

  • Can be changed

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

    to

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

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