简体   繁体   中英

Why is the lock condition not resolved between two threads using for and while loop

I am a complete beginner with threads therefore I'm not able to resolve this problem myself.

I have two threads which should run in parallel. The first thread should read in the data (simulate receive queue thread) and once data is ready the second thread shall process (processing thread) the data. The problem is, that the second thread will wait for a change of the conditional variable an infinite amount of time. If I remove the for loop of the first thread, conditional variable will notify the second thread but the thread will only execute once. Why is the conditional variable not notified if it is used within the for loop?

My goal is to read in all data of a CSV file in the first thread and store it dependent on the rows content in a vector in the second thread.

Thread one look like this

std::mutex mtx;
std::condition_variable condVar;
bool event_angekommen{false};

void simulate_event_readin(CSVLeser leser, int sekunden, std::vector<std::string> &csv_reihe)
{
    std::lock_guard<std::mutex> lck(mtx);
    std::vector<std::vector<std::string>> csv_daten = leser.erhalteDatenobj();
    for (size_t idx = 1; idx < csv_daten.size(); idx++)
    {
        std::this_thread::sleep_for(std::chrono::seconds(sekunden));
        csv_reihe = csv_daten[idx];
        event_angekommen = true;
        condVar.notify_one();
    }
}

Thread two looks like this:

void detektiere_events(Detektion detektion, std::vector<std::string> &csv_reihe, std::vector<std::string> &pir_events)
{
    while(1)
    {
        std::cout<<"Warte"<<std::endl;
        std::unique_lock<std::mutex> lck(mtx);
        condVar.wait(lck, [] {return event_angekommen; });
        std::cout<<"Detektiere Events"<<std::endl;
        std::string externes_event_user_id = csv_reihe[4];
        std::string externes_event_data = csv_reihe[6];
        detektion.neues_event(externes_event_data, externes_event_user_id);
        if(detektion.pruefe_Pir_id() == true)
        {
            pir_events.push_back(externes_event_data);
        };
    }
}

and my main looks like this:

int main(void)
{
Detektion detektion;
CSVLeser leser("../../Example Data/collectedData_Protocol1.csv", ";");

std::vector<std::string> csv_reihe;
std::vector<std::string> pir_values = {"28161","28211","28261","28461","285612"};
std::vector<std::string> pir_events;

std::thread thread[2];

thread[0] = std::thread(simulate_event_readin, leser, 4, std::ref(csv_reihe));
thread[1] = std::thread(detektiere_events,detektion, std::ref(csv_reihe), std::ref(pir_events));

thread[0].join();
thread[1].join();

}

I'm not a C++ expert, but the code seems understandable enough to see the issue.

Your thread 1 grabs the lock once and doesn't release it until the end of its lifetime. It may signal that the condition is fulfilled, but it never actually releases the lock to allow other threads to act.

To fix this, move std::lock_guard<std::mutex> lck(mtx); inside the loop, after sleeping. This way, the thread will take and release the lock on each iteration, giving the other thread an opportunity to act while sleeping.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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