Так что в основном у меня есть std::atomic<int>. Он отправляется в поток, который генерирует случайные числа:

void wind_thread(std::atomic<int>* wind)
{
    while(total_planes < max_plane )
    {
        *wind = random(1, 360);
    }
}

2 других потока получают эту переменную и что-то с ней делают, вот пример одного:

void land_thread(std::atomic<int>* wind, std::queue<Plane> *land, Runway *north_south, Runway *east_west)
{
    while(total_planes <= max_plane)
    {
        if(land->size() == 0){}
        else
        {
            std::lock_guard<std::mutex> guard(my_mutex);

            std::cout << "Plane " << land->front().get_plane_id()
            << " landed on " << wind_string(wind) << " Wind was: "
            << *wind << std::endl;

            land->front().set_details(wind_string(wind));

            if((*wind >= 46 && *wind <= 135) || (*wind >= 226 && *wind <= 315))
            {
                east_west->land(land->front());
                land->pop();
            }
            else
            {
                north_south->land(land->front());
                land->pop();
            }

            total_planes++;

        }
    }
}

Ветер в land_thread в порядке, но когда я передаю его той функции wind_string(), которая принимает std::atomic<int>* x, она получает новое значение.

Он отлично работает, если я установил блокировку на ветровой поток, но я думал, что весь смысл использования std::atomic заключается в том, что если только один поток пишет в него, мне не нужно будет использовать блокировку. Это потому, что я передаю его функции вне потока? Я искал в Интернете и все, что я нашел, это то, что мне не нужен замок. Если бы кто-нибудь мог объяснить, почему он так себя ведет, или имел бы ссылку, которая немного больше описывает, как ведет себя атомарный объект, это было бы признательно. Спасибо.

1
lciamp 4 Янв 2016 в 23:00

2 ответа

Лучший ответ

Поскольку нет никакой блокировки вокруг атомарной настройки wind, у вас нет абсолютно никакой гарантии, что вы увидите значение, которое wind имело в определенное время. Все, что дает вам atomic, - это то, что на момент установки это значение будет распространяться, так что любой, кто читает его до , когда он будет сброшен, получит установленное значение. Это также гарантирует, что все, что установлено до этого атомарного int, также будет видимым.

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

2
SergeyA 4 Янв 2016 в 20:15

1

Ваша ветровая нить будет использовать всю нить при 100% использовании, просто чтобы ваш ветер был случайным. Добавьте туда несколько sleep, чтобы избежать ненужной нагрузки на процессор или замедления работы вашей программы.
Или рассмотрите возможность создания случайного значения по запросу. (см. Почему пустой цикл использует так много процессорного времени ?)

2

Атомарный делает доступ к самим данным атомарным

            if((*wind >= 46 && *wind <= 135) || (*wind >= 226 && *wind <= 315))

Все еще можно изменить wind ПРИ КАЖДОЙ проверке. Вы можете просто заранее скопировать текущий ветер. Что-то типа:

int currentWind = wind->load();
if((currentWind >= 46 && currentWind <= 135) || (currentWind >= 226 && currentWind <= 315))  

Или используйте мьютекс, как раньше

0
Community 20 Июн 2020 в 09:12