2015-12-02 7 views

Antwort

9

Sie benötigen keinen Mutex, wenn Sie Kanäle richtig verwenden. In einigen Fällen könnte eine Lösung mit Mutex jedoch einfacher sein.

Stellen Sie nur sicher, dass die Variable (n), die die Kanalwerte enthalten, richtig initialisiert werden, bevor mehrere Gaborutinen versuchen, auf die Kanalvariablen zuzugreifen. Sobald dies geschehen ist, ist der Zugriff auf die Kanäle (z. B. das Senden von Werten an oder das Empfangen von Werten von ihnen) sicher durch das Design.

Belege, die mit Referenzen (Hervorhebungen von mir hinzugefügt):

Spec: Channel types:

Ein einzelner Kanal kann in send statements, receive operations verwendet werden, und ruft den integrierten Funktionen cap und lenvon einer beliebigen Anzahl von Goroutinen ohne weitere Synchronisation. Kanäle fungieren als First-In-First-Out-Warteschlangen. Wenn zum Beispiel eine Goroutine Werte auf einem Kanal sendet und eine zweite Goroutine sie empfängt, werden die Werte in der gesendeten Reihenfolge empfangen.

Effective Go: Concurrency: Share by communicating

Concurrent programming in vielen Umgebungen wird durch die Feinheiten erschwert erforderlich korrekten Zugriff auf gemeinsam genutzte Variablen zu implementieren. Go unterstützt eine andere Herangehensweise, bei der gemeinsame Werte auf Kanälen weitergegeben und tatsächlich niemals von separaten Ausführungsthreads gemeinsam genutzt werden. Nur eine Goroutine hat zu jedem Zeitpunkt Zugriff auf den Wert. Datenrennen können nicht auftreten. Um diese Art des Denkens zu fördern, haben wir es auf einen Slogan reduziert:

Kommunizieren Sie nicht, indem Sie Speicher teilen; Stattdessen teilen Sie Speicher durch Kommunikation.

Dieser Ansatz kann zu weit gehen. Referenzzählungen können am besten durchgeführt werden, indem man beispielsweise einen Mutex um eine Integer-Variable legt. Aber als ein Ansatz auf höherer Ebene macht die Verwendung von Kanälen zur Zugriffskontrolle das Schreiben klarer, korrekter Programme einfacher.

Dieser Artikel ist auch sehr hilfreich: The Go Memory Model

zitierte auch aus dem Paket doc von sync:

Package Sync Basissynchronisations Primitiven wie mutual exclusion Sperren zur Verfügung stellt. Anders als die Once- und WaitGroup-Typen sind meist für die Verwendung von Low-Level-Bibliotheksroutinen vorgesehen. Die Synchronisation auf höherer Ebene erfolgt besser über Kanäle und Kommunikation.

+1

Während dies eine großartige allgemeine Richtlinie ist, denke ich, dass wir wirklich betonen müssen "Dieser Ansatz kann zu weit gefasst werden." Vorbehalt. Ich habe eine Menge schauerlich komplizierten Codes daraus gesehen, mit einer Unordnung von Reaktorschleifen und Nachrichtenübergabe, wo ein einfacher Mutex genügen würde. Wie ich gerne über das Problem nachdenke: Wenn Sie versuchen, einen "gegenseitigen Ausschluss" um eine * einzige * logische Ressource zu erreichen, dann möchten Sie wahrscheinlich einen Mutex.Wenn Sie versuchen, Goroutines zu koordinieren und Synchronisationspunkte bereitzustellen, dann möchten Sie Kanäle. (Alles dazwischen kommt mit Erfahrung) – JimB

Verwandte Themen