Обновление переменной atomi c с использованием не Atomi c и наоборот - PullRequest
0 голосов
/ 05 февраля 2020

Я обновляю переменную атома c size_t, используя один поток и читая его из другого. Ниже приведен код:

Код:

// MyClass.hpp
#pragma once
#include <atomic>

class MyClass {
public:
    size_t GetVal() {
        return m_atomic_val;
    }

    void SetVal(const std::size_t val) {
        m_atomic_val = val;
    }

private:
    std::atomic<size_t> m_atomic_val{0};
};


// main.cpp
#include "MyClass.hpp"

#include <iostream>
#include <thread>

int main() {
    MyClass obj;
    obj.SetVal(4);

    std::thread my_thread = std::thread([&obj]{
       std::cout << "Thread started" << std::endl;
       std::this_thread::sleep_for(std::chrono::milliseconds(30));
        obj.SetVal(8);
    });

   std::this_thread::sleep_for(std::chrono::seconds(2));
   auto val = obj.GetVal();
   std::cout << "The value is: " << val << std::endl;
   my_thread.join();
}

Вопрос:

  • Но как Вы видите, я обновляю m_atomic_val, который является std::atomic<size_t> с size_t, который не атоми c. Будет ли это иметь плохие последствия? Это незаконно?

  • Тип возврата GetVal равен size_t, но возвращается std::atomic<size_t>. Это неправильно?

  • Итак, мой основной вопрос заключается в том, позволяет ли смешивание переменных atomi c и non atomi c так, как я делаю в примере кода?

  • Это всего лишь простой пример, демонстрирующий мой вопрос. Что, если был один поток записи и один поток чтения, которые работают одновременно, и условия гонки очень вероятны? Стоит ли переходить на использование мьютексов вместо атомарных соединений?

Среда:
Мой код работает на iOS, Android и macOS.

1 Ответ

2 голосов
/ 05 февраля 2020

Присвоение объекту atomi c примет любое значение правильного типа.

Поскольку у вас есть std::atomic<size_t>, тогда любое значение или переменная то есть (или может быть неявно преобразовано в) size_t может использоваться с правой стороны присвоения.

Что касается проблемы GetVal, std::atomic имеет преобразование Оператор , который будет делать правильные вещи, атомарно получить значение и передать его вам для возврата.

Еще одно замечание, касающееся функции GetVal: это будет только выборка значения, которое будет будь атомом c, return этого не будет. Таким образом, между выборкой и фактическим return значение m_atomic_val может измениться, но будет возвращено старое значение.

...