2014-01-30 49 views
13

分配一個指針原子在去?在golang中分配一個指針原子嗎?

我是否需要在鎖中分配一個指針?假設我只想將指針分配給nil,並希望其他線程能夠看到它。我知道在Java中我們可以使用volatile來做到這一點。但是沒有波動。

謝謝。

+0

您可能會發現[此線索](https://groups.google.com/d/msg/golang-nuts/ueSvaEKgyLY/ZW_74IC4PekJ)有趣。 – kostix

+1

您可能還會發現閱讀[「Go內存模型」](http://golang.org/ref/mem)文檔有趣 - 它定義了Go實現的需求。 AFAIK,它沒有告訴任何關於原始類型的加載/存儲操作的原子性,但只說明它們的可觀察排序。 – kostix

回答

15

唯一保證原子化的東西是sync.atomic中的操作。

所以,如果你想確定你需要鎖定,例如sync.Mutex或使用其中一個原子基元。我不推薦使用原子基元,因爲你必須在使用指針的地方使用它們,而且它們很難正確使用。

使用互斥OK Go的風格 - 你可以定義一個函數來鎖定很容易,比如像返回當前指針

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() 
} 

這些函數返回指針的一個拷貝給他們的客戶這將即使主指針被改變也保持不變。這可能會或可能不會被接受,具體取決於時間對您的要求有多重要。它應該足以避免任何未定義的行爲 - 垃圾收集器將確保指針始終保持有效,即使指向的內存不再被程序使用。

另一種方法是隻執行一次去例行程序的指針訪問,並使用通道來執行例行事務處理的命令。這會被認爲是更習慣性的,但可能不適合你的應用程序。

更新

Here is an example展示瞭如何使用atomic.SetPointer。由於使用了unsafe.Pointer,這相當難看。然而unsafe.Pointer強制編譯爲無,因此運行時成本很小。

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

我看過原子包,沒有看到原子存儲指針指向結構的方法。 StorePointer方法看起來不正確。 func StorePointer(addr * unsafe.Pointer,val unsafe.Pointer) – Koda

+1

用'StorePointer'示例更新了答案。 –

5

由於規範沒有說明你應該認爲它不是。即使它現在是原子的,它也有可能在沒有違反規範的情況下發生變化。