2016-09-21 3 views
4

how to use std::atomic<>Разница btween станд :: атомное и станд :: мьютекс

В вопросе выше, очевидно, мы можем просто использовать std::mutex, чтобы сохранить безопасность потока. Я хочу знать, когда использовать какой.

classs A 
{ 
    std::atomic<int> x; 

public: 
    A() 
    { 
     x=0; 
    } 

    void Add() 
    { 
     x++; 
    } 

    void Sub() 
    { 
     x--; 
    }  
}; 

и

std::mutex mtx; 
classs A 
{ 
    int x; 

public: 
    A() 
    { 
     x=0; 
    } 

    void Add() 
    { 
     std::lock_guard<std::mutex> guard(mtx); 
     x++; 
    } 

    void Sub() 
    { 
     std::lock_guard<std::mutex> guard(mtx); 
     x--; 
    }  
}; 
+0

'x' - это переменная экземпляра. Вы можете получить мелкозернистую блокировку, сделав мьютекс членом класса вместо того, чтобы иметь одну большую блокировку для всех потоков, изменяющую все экземпляры класса A. (Это, конечно, увеличивает размер каждого объекта A.) –

+0

Не забывайте, что даже функция доступа только для чтения также должна блокировать, по крайней мере теоретически, чтобы избежать C++ UB. (Это огромное преимущество для std :: atomic: доступ только для чтения намного дешевле). –

ответ

5

Как правило, используют std::atomic для типов POD, где основная специализация будет иметь возможность использовать что-то умное, как замок шины на CPU (который даст вам не больше накладных расходов, чем свалка трубопровода), или даже блокировка спина. В некоторых системах int может уже быть атомарным, поэтому std::atomic<int> будет эффективно специализироваться на int.

Используйте std::mutex для не-POD-типов, имея в виду, что получение мьютекса по меньшей мере на порядок медленнее, чем блокировка шины.

Если вы все еще не уверены, Измерение Производительность.

+0

'int' загружает и' int' магазины обычно являются атомарными (например, они находятся на x86), но ['my_int ++' никогда не является атомарным в многоядерных системах] (http://stackoverflow.com/questions/39393850/can- Num-быть-атомно-для-INT-NUM/39396999 # 39396999). Я бы согласился с вашей общей точкой в ​​том, что std :: atomic примитивные типы, вероятно, полезны, и все остальное, вероятно, просто сделает менее эффективную блокировку за кулисами. –

+0

'std :: atomic ' * может * быть полезным для объектов, которые соответствуют 16 байтам, но только если вы точно знаете *, что вы делаете, и ориентируетесь на платформу, которая, как вы знаете, имеет что-то вроде x86- 64 'lock cmpxchg16b', и вы создаете с помощью' -mcx16' (поскольку cmpxchg16b является расширением, к сожалению, не является частью базового x86-64, потому что он отсутствовал в первых процессорах AMD64.) См. [Мой ответ здесь] (http : //stackoverflow.com/questions/38984153/implement-aba-counter-with-c11-cas) о сравнении и замене объекта на размер двух указателей. –

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