Enthält pthread_mutex_lock eine Memory Fence-Anweisung? [duplicate]

Lesezeit: 4 Minuten

Machen pthread_mutex_lock und pthread_mutex_unlock Funktionen Aufrufspeicher Zaun/Barriere Befehle? Oder machen Sie die Anweisungen der unteren Ebene wie vergleichen_und_tauschen Selbstverständlichkeit Gedächtnisbarrieren?

Benutzeravatar von Maxim Egorushkin
Maxim Egorushkin

Rufen die Funktionen pthread_mutex_lock und pthread_mutex_unlock Memory Fence/Barrier-Anweisungen auf?

Sie tun es, ebenso wie die Erstellung von Threads.

Beachten Sie jedoch, dass es zwei Arten von Speicherbarrieren gibt: Compiler und Hardware.

Compiler-Barrieren hindern den Compiler nur daran, Lese- und Schreibvorgänge neu zu ordnen und Variablenwerte zu spekulieren, verhindern jedoch nicht, dass die CPU neu ordnet.

Die Hardwarebarrieren hindern die CPU daran, Lese- und Schreibvorgänge neu zu ordnen. Full Memory Fence ist normalerweise die langsamste Anweisung, meistens benötigen Sie nur Operationen mit Acquiring- und Release-Semantik (um Spinlocks und Mutexe zu implementieren).

Beim Multi-Threading benötigt man meistens beide Barrieren.

Jede Funktion, deren Definition in dieser Übersetzungseinheit nicht verfügbar ist (und nicht intrinsisch ist), ist a Compiler Erinnerungsbarriere. pthread_mutex_lock, pthread_mutex_unlock, pthread_create Geben Sie auch eine Hardware-Speicherbarriere aus, um zu verhindern, dass die CPU Lese- und Schreibvorgänge neu ordnet.

Aus Programmierung mit POSIX-Threads von David R. Butenhof:

Pthreads bietet ein paar grundlegende Regeln zur Speichersichtbarkeit. Sie können sich darauf verlassen, dass alle Implementierungen des Standards diese Regeln befolgen:

  1. Welche Speicherwerte ein Thread sehen kann, wenn er aufruft pthread_create kann auch durch den neuen Thread gesehen werden, wenn er beginnt. Alle Daten, die nach dem Aufruf von in den Speicher geschrieben werden pthread_create wird möglicherweise nicht unbedingt vom neuen Thread gesehen, selbst wenn der Schreibvorgang vor dem Start des Threads erfolgt.

  2. Welche Speicherwerte ein Thread sehen kann, wenn er einen Mutex entsperrt, entweder direkt oder durch Warten auf eine Bedingungsvariable, kann auch von jedem Thread gesehen werden, der später denselben Mutex sperrt. Auch hier müssen Daten, die geschrieben werden, nachdem der Mutex entsperrt wurde, nicht unbedingt von dem Thread gesehen werden, der den Mutex sperrt, selbst wenn der Schreibvorgang vor der Sperre erfolgt.

  3. Welche Speicherwerte ein Thread sehen kann, wenn er beendet wird, entweder durch Abbruch, Rückkehr von seiner Startfunktion oder durch Aufrufen pthread_exitkann auch von dem Thread gesehen werden, der sich per Aufruf mit dem beendeten Thread verbindet pthread_join. Und natürlich müssen Daten, die nach Beendigung des Threads geschrieben werden, nicht unbedingt von dem Thread gesehen werden, der beitritt, selbst wenn das Schreiben vor dem Join erfolgt.

  4. Welche Speicherwerte ein Thread sehen kann, wenn er eine Bedingungsvariable signalisiert oder sendet, kann auch von jedem Thread gesehen werden, der durch dieses Signal oder diese Sendung geweckt wird. Und noch einmal: Daten, die nach dem Signal oder der Sendung geschrieben werden, werden möglicherweise nicht unbedingt von dem Thread gesehen, der aufwacht, selbst wenn das Schreiben vor dem Aufwachen erfolgt.

Siehe auch C++ und darüber hinaus 2012: Herb Sutter – Atomwaffen für mehr Details.

Benutzeravatar von Kaz
Kaz

Bitte werfen Sie einen Blick auf Abschnitt 4.12 der POSIX-Spezifikation.

Anwendungen müssen sicherstellen, dass der Zugriff auf einen Speicherort durch mehr als einen Steuerungs-Thread (Threads oder Prozesse) so eingeschränkt ist, dass kein Steuerungs-Thread einen Speicherort lesen oder ändern kann, während ein anderer Steuerungs-Thread ihn möglicherweise ändert. Dieser Zugriff wird durch Funktionen eingeschränkt, die die Ausführung von Threads synchronisieren und auch Speicher in Bezug auf andere Threads synchronisieren. [emphasis mine]

Dann folgt eine Liste von Funktionen, die den Speicher synchronisieren, plus ein paar zusätzliche Hinweise.

Wenn dies auf einer Architektur Speicherbarriereanweisungen erfordert, müssen diese verwendet werden.

Über compare_and_swap: das ist nicht in POSIX; Überprüfen Sie die Dokumentation für das, was Sie verwenden. Zum Beispiel IBM definiert a compare_and_swap Funktion für AIX 5.3. die keine vollständige Speicherbarriere-Semantik hat. In der Dokumentationsnotiz heißt es:

Wenn “compare_and_swap” als Sperrelement verwendet wird, fügen Sie am Anfang aller kritischen Abschnitte ein isync ein.

Aus dieser Dokumentation können wir erraten, dass IBM’s compare_and_swap hat Release-Semantik: da die Dokumentation keine Barriere für das Ende des kritischen Abschnitts benötigt. Der erwerbende Prozessor muss ein isync ausgeben, um sicherzustellen, dass er keine veralteten Daten liest, aber der veröffentlichende Prozessor muss nichts tun.

Auf der Befehlsebene haben einige Prozessoren Vergleichen und Austauschen mit bestimmten Synchronisierungsgarantien, andere nicht.

  • Schöner Hinweis auf POSIX, ich wusste nicht, dass POSIX die genaue Liste der Funktionen dafür angegeben hat. +1

    – Maxim Egorushkin

    10. Juni 2014 um 15:24 Uhr

1437480cookie-checkEnthält pthread_mutex_lock eine Memory Fence-Anweisung? [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy