2014-01-30 9 views
13

Wird ein Zeiger atomar in go zugewiesen?Wird in Golang ein Zeiger atomar zugewiesen?

Muss ich einen Zeiger in einem Schloss zuweisen? Angenommen, ich möchte den Zeiger nur auf Null setzen und möchte, dass andere Threads ihn sehen können. Ich weiß, in Java können wir flüchtig dafür verwenden. Aber es gibt kein flüchtiges in gehen.

Danke.

+0

Vielleicht finden Sie [dieses Thema] (https://groups.google.com/d/msg/golang-nuts/ueSvaEKgyLY/ZW_74IC4PekJ) interessant. – kostix

+1

Sie können das Dokument ["Go memory model"] (http://golang.org/ref/mem) auch amüsant finden - es definiert die Anforderungen für Go-Implementierungen. AFAIK, es sagt nichts über die Atomität der Lade-/Speicheroperationen von primitiven Typen aus, sondern spricht nur über die beobachtbare Anordnung von ihnen. – kostix

Antwort

15

Die einzigen Dinge, die garantiert atomar sind, sind die Operationen in sync.atomic.

Also, wenn Sie sicher sein wollen, müssen Sie entweder eine Sperre nehmen, zB sync.Mutex oder eines der atomaren Primitiven verwenden. Ich empfehle jedoch nicht, die atomaren Primitiven zu verwenden, da Sie sie überall verwenden müssen, wo Sie den Zeiger verwenden, und sie sind schwer zu bekommen.

den Mutex zu verwenden ist OK Go-Stil - Sie eine Funktion definieren, könnten den aktuellen Zeiger mit Verriegelungs sehr leicht, zum Beispiel so etwas wie

import "sync" 

var secretPointer *int 
var pointerLock sync.Mutex 

func CurrentPointer() *int { 
    pointerLock.Lock() 
    defer pointerLock.Unlock() 
    return secretPointer 
} 

func SetPointer(p *int) { 
    pointerLock.Lock() 
    secretPointer = p 
    pointerLock.Unlock() 
} 

Diese Funktionen geben eine Kopie des Zeigers an ihren Kunden zurück die konstant bleiben, auch wenn der Master-Zeiger geändert wird. Dies kann oder kann nicht akzeptabel sein, abhängig davon, wie zeitkritisch Ihre Anforderung ist. Es sollte ausreichen, um ein undefiniertes Verhalten zu vermeiden - der Garbage Collector stellt sicher, dass die Zeiger immer gültig sind, selbst wenn der Speicher, auf den verwiesen wird, nicht mehr von Ihrem Programm verwendet wird.

Ein alternativer Ansatz wäre, nur den Zeiger Zugriff von einer Routine zu tun und Kanäle zu verwenden, die Routine in Dinge tun gehen. Das wäre idiomatischer zu gehen, aber möglicherweise nicht genau Ihre Anwendung.

aktualisieren

Here is an example zeigt, wie atomic.SetPointer zu verwenden. Es ist ziemlich hässlich aufgrund der Verwendung von unsafe.Pointer. Jedoch kompiliert unsafe.Pointer Umwandlungen zu nichts, so dass die Laufzeitkosten gering sind.

import (
    "fmt" 
    "sync/atomic" 
    "unsafe" 
) 

type Struct struct { 
    p unsafe.Pointer // some pointer 
} 

func main() { 
    data := 1 

    info := Struct{p: unsafe.Pointer(&data)} 

    fmt.Printf("info is %d\n", *(*int)(info.p)) 

    otherData := 2 

    atomic.StorePointer(&info.p, unsafe.Pointer(&otherData)) 

    fmt.Printf("info is %d\n", *(*int)(info.p)) 

} 
+0

Ich habe mir das atomare Paket angeschaut und keine Methode zum atomaren Speichern des Zeigers auf eine Struktur gefunden. Die Methode StorePointer sieht nicht wie die richtige aus. func StorePointer (addr * unsafe.Pointer, val unsafe.Pointer) – Koda

+1

Die Antwort wurde mit einem 'StorePointer' Beispiel aktualisiert. –

5

Da die Spezifikation nicht spezifiziert, sollten Sie davon ausgehen, dass es nicht ist. Selbst wenn es momentan atomar ist, ist es möglich, dass es sich ändern kann, ohne jemals die Spezifikation zu verletzen.

Verwandte Themen