2013-05-04 9 views
6

Załóżmy, że mam następującą funkcję.Czy muszę używać lotnego słowa kluczowego, jeśli zadeklaruję zmienną między muteksami i zwrócę ją?

std::mutex mutex; 

int getNumber() 
{ 
    mutex.lock(); 
    int size = someVector.size(); 
    mutex.unlock(); 
    return size; 
} 

Czy to jest miejsce do użycia słowa kluczowego volatile podczas deklarowania rozmiaru? Czy zwrócisz optymalizację wartości lub coś jeszcze złamie ten kod, jeśli nie używam lotnego? Rozmiar someVector można zmienić z dowolnego z wielu wątków programu i zakłada się, że tylko jeden wątek (inny niż modyfikatory) wywołuje getNumber().

+2

Tutaj jest wyjaśnienie niestabilności: http://stackoverflow.com/questions/154551/volatile-vs-interlocked-vs-lock – Will

+5

@Chyba nie uważam, że C# 'volatile' jest tym samym co C++' volatile' (choć byłoby to bezużyteczne w obu językach w tej sytuacji). –

+1

Ooops, nie widziałem, żeby ta odpowiedź była dla C++. Oto lepsze wyjaśnienie volatile: http://stackoverflow.com/questions/72552/why-does- volatile-exist – Will

Odpowiedz

5

Nie podano, jaka jest zmienna mutex, ale zakładając, że jest to std::mutex (lub coś podobnego, co ma na celu zagwarantowanie wzajemnego wykluczenia), kompilator nie może wykonywać wielu optymalizacji. Nie musisz więc martwić się o optymalizację wartości zwracanej lub inną optymalizację, która umożliwia wykonanie zapytania poza blokiem mutex.

Jednak po zwolnieniu blokady mutex, inny wątek jest wolny, aby uzyskać dostęp do wektora i ewentualnie go zmutować, zmieniając w ten sposób rozmiar. Teraz liczba zwrócona przez twoją funkcję jest nieaktualna. Jak wspomina Mats Petersson w swoim answer, jeśli jest to problem, to blokada muteks musi zostać nabyta przez wywołującego getNumber() i jest utrzymywana do czasu, aż wywołujący zostanie użyty przy użyciu wyniku. Zapewni to, że rozmiar wektora nie zmieni się podczas operacji.


jawne wywołanie mutex::lock następnie mutex::unlock szybko staje się niewykonalne dla bardziej skomplikowanych funkcji obejmujących wyjątki, wiele instrukcji powrotne itp Znacznie łatwiej Alternatywą jest użycie std::lock_guard nabyć blokadę mutex.

int getNumber() 
{ 
    std::lock_guard<std::mutex> l(mutex); // lock is acquired 
    int size = someVector.size(); 
    return size; 
} // lock is released automatically when l goes out of scope 
8

Nie. Ale uwaga: size może nie odzwierciedlać rzeczywistego rozmiaru PO uwolnieniu muteksu.

Edycja: Jeśli musisz wykonać pewne zadanie, które polega na poprawnym size, musisz zawinąć całe to zadanie za pomocą muteksu.

+0

Funkcja jest obecnie używana tylko jako podpowiedź, więc precyzja nie jest w tej chwili potrzebna . Dzięki za heads-up. – Etherealone

1

Lotny to słowo kluczowe, które używasz do poinformować kompilator, dosłownie faktycznie zapis lub odczyt zmiennej i nie stosować żadnych optymalizacje. Oto przykład:

int example_function() { 
int a; 
volatile int b; 
a = 1; // this is ignored because nothing reads it before it is assigned again 
a = 2; // same here 
a = 3; // this is the last one, so a write takes place 
b = 1; // b gets written here, because b is volatile 
b = 2; // and again 
b = 3; // and again 
return a + b; 
} 

Jaki jest faktyczny użytek z tego? Widziałem to w funkcjach opóźnienia (utrzymuję procesor zajętości przez trochę, licząc do liczby) oraz w systemach, w których kilka wątków może wyglądać na tę samą zmienną. Czasami może pomóc nieco w przypadku wielowątkowych rzeczy, ale nie jest to naprawdę nicią do gwintowania i na pewno nie jest srebrną kulą.

Powiązane problemy