2016-12-22 2 views
2

Может кто-то, пожалуйста, помогите мне понять, что я делаю неправильно здесь? Когда я делаю члены данных класса не атомарными, он работает нормально.Атомный элемент данных, вызывающий из потока

class AtomicTest 
{ 
    atomic<int> A{ 0 }; 
    atomic<int> B{ 0 }; 
public : 
    AtomicTest() { } 
    void func1() 
    { 
     A = 1; 
     cout << "func1 " << A << endl;; 
    } 
    void func2() 
    { 
     cout << "func2 " << A << endl; 
     A = A + 1; 
     cout << A << endl; 
    } 
}; 

int main() 
{ 
    AtomicTest a; 
    thread t1(&AtomicTest::func1, std::ref(a)); // I tried to move as well, i know ref would share data between two threads but i can use mutex to protect data if its needed but i cannot even call the func1 

    //thread t2(&AtomicTest::func2, std::ref(a)); 
    t1.join(); 
    //t2.join(); 

    return 0; 
} 
+0

Я не думаю, что вы попытались: 'std :: bind (& AtomicTest :: func1, std :: ref (a))' как единственный параметр для конструктора потоков? – WhozCraig

+0

Я уверен, что нет, потому что я понятия не имел, почему он работает таким образом. Могу ли я узнать, почему это не сработало, и с помощью bind? –

+0

Может кто-нибудь просветить меня о том, в чем проблема? Использование clang это прекрасно работает для меня. –

ответ

0

Благодаря параллельности без дополнительной синхронизации в этом случае невозможно предсказать поведение программы:

A = A + 1; 

Эта простая линия состоит из 1 атомное load и 1 атомных store операций. Даже заказ памяти по умолчанию (std::memory_order_seq_cst) не даст вам никаких гарантий относительно смешанного одновременного выполнения этих двух потоков. Стандарт говорит, что такой случай имеет неопределенное поведение - есть гонка данных для вашей переменной (неважно, это atomic или нет).

Попробуйте добавить некоторые блокирующие примитивы (например, std::mutex) или изменить логику для использования специальных атомных функций (таких как fetch_add, exchange и т. Д.). См. Больше на странице cpp-reference.

+0

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

+0

Извините, может быть, я не понял точную проблему, и очевидный способ заставить работать код - проверить директиву 'include' и использовать' --std = C++ 11'. Btw (с необходимыми включает в себя, директивы и библиотеки) компилируется и работает очень хорошо для всех современных компиляторов (см. Этот хороший инструмент [http://gcc.godbolt.org/)). – Trollliar

Смежные вопросы