Тупик при использовании condition.wait () - PullRequest
0 голосов
/ 18 июня 2019

Код найден здесь: http://coliru.stacked -crooked.com / a / 7942a18fe11ea544

Я экспериментирую с условием. Жду без перерыва и нахожусь в тупике. Суть того, что я пытаюсь сделать, это сидеть в замке, пока я не определю, что создал новый файл. Я бы установил флаг и уведомил бы поток, который затем (в моей реальной программе) вызовет функцию обратного вызова. в конце работы я хочу закрыть все свои темы. Я установил для моей переменной цикла значение false, а затем уведомил об этом, что, как я предполагал, разблокирует поток. Я ошибаюсь, что это будет игнорировать то, что оценил предикат?

Может ли кто-нибудь предложить лучший макет потока, который бы исправил тупик? Спасибо.

#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <atomic>
#include <mutex>
#include <condition_variable>

using namespace std::chrono_literals;
std::atomic_bool new_file_created_{false};
std::atomic_bool run_data_logger_{false};
std::condition_variable file_monitor_condition_;
std::mutex file_monitor_mutex_;
std::thread test_thread_;

void file_monitor_thread_func()
{
    using namespace std::chrono_literals;
    while (run_data_logger_)
    {
        std::unique_lock<std::mutex> lock(file_monitor_mutex_);
        file_monitor_condition_.wait(lock, [] { return new_file_created_.load(); });
        if (new_file_created_)
        {
            std::cout<< "New File Created" << std::endl;
            new_file_created_ = false;                       
            //do some stuff
        }
        else
        {}                
    }
}

void end_the_thread()
{
    std::cout << "Ending the Thread" << std::endl;
    run_data_logger_ = false;
    file_monitor_condition_.notify_one();
    if (test_thread_.joinable())
        test_thread_.join();

    std::cout << "Thread Ended" << std::endl;
}

void trigger_new_file()
{
   new_file_created_ = true;
   file_monitor_condition_.notify_one(); 
}

void start_the_thread()
{
    run_data_logger_ = true;
    test_thread_ = std::thread(file_monitor_thread_func);

    trigger_new_file();
}

int main()
{
    for (int j = 0; j<10; j++)
    {

        start_the_thread();
        std::this_thread::sleep_for(500ms);            
        end_the_thread();
    }
}

Ответы [ 2 ]

3 голосов
/ 19 июня 2019

После того, как new_file_created_ станет true в первый раз, file_monitor_thread_func сбрасывает его до false, затем зацикливается и ждет, пока оно снова не станет true.Но никто никогда не установит его снова на true.

0 голосов
/ 27 июня 2019

A condition_variable используется вместе с mutex, что является , а не косметической функцией. Вы, кажется, под впечатлением, что

    std::unique_lock<std::mutex> lock(file_monitor_mutex_);

достаточно для выполнения условия wait; но мьютекс концептуально имеет смысл, только если он используется для взаимного исключения . Вы не используете его как таковой, мьютекс блокируется только внутри file_monitor_thread_func, поэтому взаимное исключение при операциях изменения состояния не гарантируется.

Контрольный признак того, что вы используете монитор неправильно, заключается в том, что вы почувствовали необходимость использовать атомарные объекты, поскольку взаимное исключение (которое является обязательным условием) гарантирует, что можно использовать обычные объекты.

Просто невозможно объединить условие и атомарные объекты . Они принадлежат разным конструкциям.

...