Globale statische Variablen Multithread sicher machen
-
27-09-2019 - |
Frage
Ich habe globale statische Variablen in einer C -Bibliothek, die Ausnahmen in einem Multithread -Lauf generieren. Ich muss sie in irgendeiner Weise sicher machen (dh jeder Thread sollte sich auf eine andere Instanz dieser Variablen beziehen). Irgendwelche empfohlenen Methoden?
Lösung
Es gibt keinen Standardweg, der in allen C-Implementierungen funktioniert, aber es gibt implementierungsspezifische Lösungen. Zum Beispiel mit Microsofts Compiler (siehe Die Dokumente),
__declspec( thread ) int tls_i = 1;
macht tls_i
Live in Thread-lokaler Speicher (jeder Thread hat eine eigene separate Instanz dieser Variablen). Mit GCC, die Syntax ist
__thread int tls_i;
Möglicherweise möchten Sie auch die überprüfen Wikipedia -Eintrag zum Thema.
Andere Tipps
Erste Frage:
- Benötigen die Threads ihre eigenen Kopien der Variablen?
- Oder müssen sie den Zugriff auf eine einzelne gemeinsame Kopie koordinieren?
Wenn Sie erstere benötigen, haben die anderen Antworten Vorschläge zum "Thread-lokalen Speicher" gemacht.
Wenn Sie das letztere benötigen, müssen Sie irgendwie sicherstellen, dass ein geeignetes Mutex für diese Variablen (der Umfang des Mutex ist eines der Probleme, mit denen Sie konfrontiert sind) und dass die Threads alle den Mutex verwenden und den Mutex freigeben. Das ist schwieriger. Es kann sogar sein, dass Sie Funktionen bereitstellen müssen, die den Zugriff auf die Variablen steuern.
Die Standardvariable errno
Kann ein veränderbares LVALUE sein:
extern int *_errno_func(void);
#define errno (*(_errno_func)())
In einer Thread -Anwendung (kompiliert mit -Dresinant) ist dies passiert. Auf macOS X scheint es sowieso zu sein (sie verwenden den Namen __error
Anstatt von _errno_func
; Beide sind im Namespace der Implementierung).
Möglicherweise möchten oder müssen Sie etwas Ähnliches für Ihre Variablen tun. Die Tatsache, dass Sie sagen, dass sie statisch sind, verbessert die Dinge ein wenig. Sie haben nur eine Datei, mit der Sie sich befassen müssen (es sei denn, Sie sind unachtsam genug, um Zeiger auf diese Variablen zurückzugeben).
Was Sie brauchten, ist TLS (Lokalspeicher Thread), was auch als bekannt ist als Thread-spezifische Daten oder Thread-private Daten. Dieser Mechanismus kann jedem Thread garantieren, dass er auf seine eigene separate Kopie der Daten zugreifen kann, ohne sich über die Synchronisierung des Zugriffs mit anderen Threads zu sorgen.
Es gibt zwei Methoden zur Verwendung von TLS:
Implizit: Verwenden von Schlüsselwort
Fenster: __declspec (Thread) int tls_var = 10;
Linux mit GCC: __Thread int tls_var = 10
Explizit: Verwenden spezifischer TLS -verwandter API
Fenster:
- Tlsalloc (): Speicher Speicher für TLS -Daten zuweisen
- Tlsfree (): Befreie den Speicher der TLS -Daten
- TlssetValue (): Setzen Sie den Wert von TLS
- TlsgetValue (): Holen Sie sich den Wert von TLS
Weitere Informationen finden Sie unter MSDN.
Linux mit GCC:
- pthread_key_create (): Erstellen Sie die TLS -Daten
- pthread_key_delete (): Zählen Sie die TLS -Daten
- pthread_getSpecific (): Erhalten Sie den Wert von TLS
- pThread_SetSpecific(): Setzen Sie den Wert von TLS
Die meisten Compiler haben eine Möglichkeit, Thread-lokaler Speicher zu bezeichnen. Angenommen, es ist verfügbar, wollen Sie das.