Должен ли я защищать операции на примитивных типах с мьютексами для обеспечения безопасности потоков в C ++? - PullRequest
3 голосов
/ 01 сентября 2010

Каков наилучший подход для обеспечения безопасности потоков при довольно простых операциях?

Рассмотрим пару функций:

void setVal(int val)
{
    this->_val = val;
}

int getVal() {
     return this->_val;
}

Поскольку даже присваивания примитивных типов не гарантируются как атомарные, я должен изменить каждый метод получения и установки в программе следующим образом:быть потокобезопасным?

void setVal(int val)
{
    this->_mutex.lock();
    this->_val = val;
    this->_mutex.unlock();
}

int getVal() {
     this->_mutex.lock();
     int result = this->_val;
     this->_mutex.unlock();
     return result;
}

Ответы [ 4 ]

6 голосов
/ 01 сентября 2010

Используете ли вы _val в нескольких потоках?Если нет, то нет, вам не нужно синхронизировать доступ к нему.

Если он используется из нескольких потоков, то да, вам нужно синхронизировать доступ, используя мьютекс или атомарный тип.(как std::atomic<T> в C ++ 0x, хотя другие библиотеки потоков также имеют нестандартные атомарные типы).

1 голос
/ 05 мая 2011

На 32-разрядных платформах x86 чтение и запись 32-разрядных значений, выровненных по 4-байтовой границе, являются атомарными.На 64-битных платформах вы также можете рассчитывать на 64-битную загрузку и хранение 8-байтовых выровненных значений, которые также будут атомарными.Процессоры SPARC и POWER также работают подобным образом.

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

1 голос
/ 01 сентября 2010

Мьютексы очень дороги, так как они могут быть разделены между процессами. Если состояние, к которому вы ограничиваете доступ, ограничено только потоками в текущем процессе, перейдите к чему-то гораздо менее тяжелому, например, к критическому разделу или семафору.

0 голосов
/ 01 сентября 2010
int getVal() { 
     this->_mutex.lock(); 
     int result = this->_val; 
     this->_mutex.unlock(); 
     return result; 
}

Что именно вы надеетесь достичь с помощью этого?Конечно, вы остановили изменение this->_val перед сохранением в result, но оно все еще может измениться до того, как будет возвращен результат - или между возвратом и назначением тому, что вы ему присвоили - или микросекунду позже.Независимо от того, что вы делаете, вы просто получите снимок движущейся цели.Смирись с этим.

void setVal(int val)          
{          
    this->_mutex.lock();          
    this->_val = val;          
    this->_mutex.unlock();          
} 

Точно так же, что это тебе покупает?Если вы вызываете setVal(-5) и setVal(17) из разных потоков одновременно, какое значение должно быть после завершения обоих?У вас возникли проблемы с тем, чтобы убедиться, что первым запустится и первым закончится, но как это поможет получить «правильное» значение?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...