читать значение переменной в main из потока в c ++ - PullRequest
0 голосов
/ 04 мая 2019

Мне нужен поток, который выполняет функцию в цикле while (скажем, увеличивает значение int).В основном мне нужно иметь цикл while, который выполняет некоторую функцию (скажем, цикл for, которая считает от 0 до 5), а затем читает текущее значение переменной в потоке.Поток должен продолжать выполнять свой цикл while независимо от того, что происходит в main.Однако значение переменной потока не должно изменяться, пока main читает переменную.

Полагаю, эту проблему можно решить с помощью атомарного.Однако это проблема игрушки, в которой переменная в потоке является int.В моей актуальной задаче переменная потока типа Eigen :: quaternionf или float [4].Поэтому мне нужно убедиться, что весь Eigen :: quaternionf или float [4] поддерживается постоянным при чтении из main.

Cout в потоке предназначен только для отладки.Если код работает с безопасностью потока, его можно удалить.Я читал из другого поста, что при использовании cout безопасным для потока способом, возможно, потребуется написать новую оболочку cout с мьютексом.Я хочу этого избежать.

Моя главная задача - прочитать переменную в правильном порядке в main.

Мой код не работает (сегодня мой первый день с многопоточностью) и ниже, как и наблюдалосьвывод (выбранные части).код не может поддерживать порядок вывода с помощью cout (искаженный вывод).Также я не уверен, что переменная потока правильно прочитана главной.

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

int i = 0;


void safe_increment(std::mutex& i_mutex)
{

    while(1)
    {

    std::lock_guard<std::mutex> lock(i_mutex);
    ++i;

    std::cout << "thread: "<< std::this_thread::get_id() << ", i=" << i << '\n';
    }

}

int main()
{
    std::mutex i_mutex;  

    std::thread t1(safe_increment, std::ref(i_mutex));


   while(1)
{
    for(int k =0; k < 5; k++)
    {
    std::cout << "main: k =" << k << '\n';
    }

    std::lock_guard<std::mutex> lock(i_mutex);
    std::cout << "main: i=" << i << '\n';
}
}

Вывод (выбранные части), который я получаю,

thread: 139711042705152, i=223893
thread: 139711042705152, i=223894
thread: 139711042705152, i=223895
main: i=223895
main: k =0
thread: main: k =1139711042705152
main: k =2
main: k =3
, i=main: k =4
223896
thread: 139711042705152, i=223897
thread: 139711042705152, i=223898



thread: 139711042705152, i=224801
thread: 139711042705152, i=224802
main: i=224802
main: k =0
main: k =1
thread: main: k =2
main: k =3
main: k =4
139711042705152, i=224803
thread: 139711042705152, i=224804
thread: 139711042705152, i=224805

Ответы [ 2 ]

1 голос
/ 04 мая 2019

i правильно синхронизирован с мьютексом. отлично сработано! очевидно, что это выполняется до тех пор, пока вы не заставите его остановиться, поэтому, когда вы найдете лучший способ завершить выполнение, обязательно join в вашем потоке.

для исправления искажений необходимо синхронизироваться на std::cout:

int main()
{
    std::mutex i_mutex;  

    std::thread t1(safe_increment, std::ref(i_mutex));

    while(1)
    {
        std::lock_guard<std::mutex> lock(i_mutex);//moved up here to sync on std::cout << k
        for(int k =0; k < 5; k++)
        {
            std::cout << "main: k =" << k << '\n';
        }

        std::cout << "main: i=" << i << '\n';
        if (i > 100) break;
    }

    t1.join(); //thread will continue and main will wait until it is done
    //your thread needs to have some way out of its while(1) as well.
}

нить может быть такой:

void safe_increment(std::mutex& i_mutex)
{
    while(1)
    {

    std::lock_guard<std::mutex> lock(i_mutex);
    ++i;

    std::cout << "thread: "<< std::this_thread::get_id() << ", i=" << i << '\n';
    if (i > 111) break;
    }

}
0 голосов
/ 04 мая 2019

Вот асинхронное и атомарное предложение:

#include <future>
#include <iostream>
#include <atomic>

std::atomic<int> i{0};
std::atomic<bool> stop{false};

void safe_increment()
{
    while (!stop)
    {
        ++i;
        std::cout << "thread: "<< std::this_thread::get_id() << ", i=" << i << '\n';
    }
}

int main()
{
    auto task = std::async(std::launch::async, safe_increment);

    while(1)
    {
        for(int k =0; k < 5; k++)
        {
            std::cout << "main: k =" << k << '\n';
        }

        std::cout << "main: i=" << i << '\n';

        if (i > 5000) {
            stop = true;
            break;
        }
    }

    task.get();
}

Оно не совсем эквивалентно вашему коду, поскольку во время операций stdout блокировка не удерживается, но я думаю, что эти разногласия не были преднамеренными.

...