2013-03-30 11 views
6

Niedawno dowiedziałem się, że kompilatory zoptymalizują kod poprzez zmianę kolejności instrukcji i że można to kontrolować za pomocą barier.Czy potrzebuję ogrodzenia lub bariery lub czegoś, gdy blokady/blokady mutex są zakopane głęboko w wywołaniach funkcji?

IIRC, blokowania mutex sprawia barierę i odblokowywanie mutex również sprawia, barierę, aby zachować kod wewnątrz sekcji krytycznej przed dostaniem się.

Więc pthread_mutex_lock i pthread_mutex_unlock niejawnie musi być te „przeszkody”. Co jeśli mam taką klasę, która otula mój muteks?

class IMutex { 
public: 
    virtual void lock() = 0; 
    virtual void unlock() = 0; 
}; 

wydaje mi się, że kompilator nie będzie wiedział, że dzwonię pthread_mutex_lock() wewnątrz zamka() i pthread_mutex_unlock() wewnątrz unlock(), bo to wszystko virtual'd dalej.

doprowadzi to do błędów? Czy muszę jakoś ręcznie określać bariery?

+2

Myślę, że wywołanie funkcji byłoby przeszkodą w ruchu kodu kompilatora. Używamy muteksów i nie dodajemy żadnych barier. Istnieją bariery pamięci, które są czymś zupełnie innym. –

+0

oh, to ma sens. dzięki! – Verdagon

+0

Tak, żaden porządny kompilator nie zmieni kolejki wokół wirtualnego wywołania funkcji ... –

Odpowiedz

6

Zmiana kolejności instrukcje odbywa się na różnych poziomach. Najbardziej oczywistym jest kompilator, a mniej oczywistym jest CPU (który jest w locie). Jednak funkcje synchronizacji prawie zawsze są ogrodzeniem, które uniemożliwia wykonanie instrukcji przed i po zmianie ogrodzenia.

Więc jeśli twój wirtualny lock dzwoni pthread_mutex_*() to twoje funkcje wirtualne zawierają ogrodzenie.

Więc krótka odpowiedź brzmi: Nie, to nie będzie prowadzić do błędów.

Istnieje również lotny słów kluczowych, które w zależności od platformy może również generować ogrodzenia. Jednak używanie niestabilnych słów kluczowych znacznie utrudnia wykrycie tych ogrodzeń, ponieważ za każdym razem, gdy używasz zmiennej lub funkcji, która jest niestabilna, wprowadzasz ogrodzenie. Tak więc radzimy korzystać z funkcji synchronizacji platformy.

Jedynym momentem, w którym należy pamiętać o ogrodzeniach, jest sytuacja, gdy nie używa się obiektów współbieżności do wykonania synchronizacji (np. Przy użyciu obiektu bool zamiast muteksu).

+1

Nie polecam niestabilności na elementach danych, ponieważ może to wprowadzić barierę pamięci, która ponownie może ukryć błąd wyścigu danych z powodu "rzeczywistego" muteksu mając inny błąd ... Używaj właściwych funkcji synchronizacji zamiast zmiennych. – ActiveTrayPrntrTagDataStrDrvr

+0

Dzięki @ActiveTrayPrntrTagDataStrDrvr Zaktualizowałem odpowiedź, aby uwzględnić Twoją rekomendację. – DevWouter

Powiązane problemy