Является ли return атомарным, и я должен использовать временный в getter, чтобы быть потокобезопасным? - PullRequest
5 голосов
/ 03 сентября 2010

Нужно ли здесь использовать временный файл, чтобы быть потокобезопасным?

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

Я дам вам разборку простой тестовой функции RAII

int test()
{
    RAIITest raii; //let's say it's a scoped lock
    return 3;
}


 {
     0x004013ce <_Z4testv>:    push  %ebp
     0x004013cf <_Z4testv+1>:  mov   %esp,%ebp
     0x004013d1 <_Z4testv+3>:  sub   $0x28,%esp
     return 3;
     0x004013d4 <_Z4testv+6>:  lea   -0x18(%ebp),%eax
     0x004013d7 <_Z4testv+9>:  mov   %eax,(%esp)
     0x004013da <_Z4testv+12>: call  0x4167a0 <_ZN8RAIITestD1Ev>  //here destructor is called
     0x004013df <_Z4testv+17>: mov   $0x3,%eax //here result is pushed onto the stack
 }
 0x004013e4 <_Z4testv+22>: leave 
 0x004013e5 <_Z4testv+23>: ret   

компилятор gcc/ г ++ 3,4,5

Ответы [ 4 ]

5 голосов
/ 03 сентября 2010

Если доступ к this->_val синхронизирован с this->_mutex, то у вас нет выбора способа написания кода в данный момент.Вам нужно прочитать this->_val, прежде чем разблокировать мьютекс, и вы должны разблокировать мьютекс, прежде чем вернуться.Переменная result необходима для получения этого порядка действий.

Если вы используете lock_guard (или scoped_lock в Boost), то вам не нужно использовать временную, поскольку блокировкамьютекс будет освобожден, когда функция вернется.Например, используя библиотеку потоков C ++ 0x:

int getVal() {
    std::lock_guard<std::mutex> lock(_mutex);
    return this->_val;
}   // lock is released by lock_guard destructor 
1 голос
/ 03 сентября 2010

Да, если вы используете явную блокировку () / разблокировку ().Нет, если вы строите объект блокировки в стеке, и его деструктор выполняет разблокировку.

0 голосов
/ 03 сентября 2010

Вы можете сделать это чисто, если ваш мьютекс инкапсулирован в scoped_lock, который разблокируется при уничтожении:

 int getVal() {
       scoped_lock lockit(_mutex);
       return _val;
 }

И да, вам нужно удерживать замок, пока он не вернется.

0 голосов
/ 03 сентября 2010

Нет - компилятор автоматически создает временное значение для возвращаемого значения.Обычно вам не нужно защищать чтение с помощью мьютекса, поэтому, даже если он многопоточный, достаточно просто return _val;.

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

...