Как разделить общий ресурс между двумя потоками? - PullRequest
2 голосов
/ 07 июня 2019

Вот мой фрагмент кода, где я пытаюсь получить доступ к ресурсу в двух разных потоках в режиме отсоединения, но я не могу прочитать значение обновления m_dataLoaded во втором потоке.Он продолжает ждать, даже если условие выполнено.Я не понимаю логику этого и как этого добиться ??

Файл заголовка application.h

#ifndef APPLICATION_H
#define APPLICATION_H

#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>

class Application
{
public:
    Application();

    bool isDataLoaded();

    void loadData();

    void mainTask();

private:
    bool m_dataLoaded;
    std::condition_variable m_condVar;
    std::mutex m_mutex;
};

#endif // APPLICATION_H

Исходный файл application.cpp

#include "application.h"

Application::Application()
           : m_dataLoaded(false)
{
}

bool Application::isDataLoaded()
{
     return m_dataLoaded;
}

void Application::loadData()
{
    std::cout << "Inside loadData" << std::endl;

    std::lock_guard<std::mutex> gaurd(m_mutex);

    while(true)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));

        m_dataLoaded = true;

        if(m_dataLoaded)
        {
            m_condVar.notify_one();
        }
    }
}

void Application::mainTask()
{
    std::cout << "Inside mainTask" << std::endl;

    std::unique_lock<std::mutex> u_lock(m_mutex);

    while(true)
    {
        std::cout << "Waiting..." << std::endl;

        m_condVar.wait(u_lock, std::bind(&Application::isDataLoaded, this));

        std::cout << "Start Data Processing: " << std::endl;

        m_dataLoaded = false;
    }

    std::cout << "Break out of the loop" << std::endl;
}

основной файл main.cpp

#include "application.h"

int main()
{
    Application *app = new Application;

    std::thread *thread_1 = new std::thread(&Application::mainTask, app);
    std::thread *thread_2 = new std::thread(&Application::loadData, app);

    thread_2->detach();
    thread_1->detach();

    while(1)
    {
    }

    return 0;
}

вышеприведенный фрагмент кода thread_1 продолжает ждать ... Я не понимаю, почему это происходит.Любая помощь будет оценена ...

1 Ответ

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

И был вызван rafix07 в разделе комментариев вашего вопроса - main, вероятно, завершает работу и инициирует завершение программы, прежде чем какой-либо поток сможет что-либо сделать.Но это не единственная ошибка.

Вы забыли выйти из цикла в mainTask.Ваш код в mainTask застрял в цикле while(true) - даже после того, как isDataLoaded() станет истинным выражением.

while (true) // <<=== INFINITE LOOP
{
    std::cout << "Waiting..." << std::endl;

    m_condVar.wait(u_lock, std::bind(&Application::isDataLoaded, this));

    std::cout << "Start Data Processing: " << std::this_thread::get_id() << std::endl;

}

Традиционный подход "цикла", который я предпочитаю, потому что он напоминает шаблон pthreads проверки условиясначала, затем ожидание, а затем проверка снова (из-за ложных пробуждений).

while (!isDataLoaded())
{
    std::cout << "Waiting..." << std::endl;

    m_condVar.wait(u_lock);
}

std::cout << "Start Data Processing: " << std::this_thread::get_id() << std::endl;

Или без использования цикла, просто используйте подход предикатов без явного цикла:

std::cout << "Waiting..." << std::endl;

m_condVar.wait(u_lock, [this]() {
    return isDataLoaded();
});

std::cout << "Start Data Processing: " << std::this_thread::get_id() << std::endl;

Вот ваша программа comlete, измененная с исправлениями:

#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>


class Application
{
public:
    Application();

    bool isDataLoaded();

    void loadData();

    void mainTask();

private:
    bool m_dataLoaded;
    std::condition_variable m_condVar;
    std::mutex m_mutex;
};

Application::Application()
    : m_dataLoaded(false)
{
}

bool Application::isDataLoaded()
{
    return m_dataLoaded;
}

void Application::loadData()
{
    std::cout << "Inside loadData" << std::endl;

    std::this_thread::sleep_for(std::chrono::milliseconds(1000));

    std::lock_guard<std::mutex> gaurd(m_mutex);

    m_dataLoaded = true;

    m_condVar.notify_all();
}

void Application::mainTask()
{
    std::cout << "Inside mainTask" << std::endl;

    std::unique_lock<std::mutex> u_lock(m_mutex);

    while (!isDataLoaded())
    {
        std::cout << "Waiting..." << std::endl;

        m_condVar.wait(u_lock);
    }

    std::cout << "Done Waiting" << std::endl;
}

int main()
{
    Application *app = new Application;

    std::thread *thread_1 = new std::thread(&Application::mainTask, app);
    std::thread *thread_2 = new std::thread(&Application::loadData, app);

    std::cout << "Thread_1 id: " << thread_1->get_id() << std::endl;

    thread_2->detach();
    thread_1->detach();

    while (true)
        std::this_thread::sleep_for(std::chrono::milliseconds(100000));

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...