原子レベルで動作することが保証されているのは、sync.atomicの操作だけです。
ロックを取る必要があるかどうかを確認するには、例えばsync.Mutexを使用するか、原子プリミティブのいずれかを使用します。ポインタを使用するあらゆる場所でそれらを使用しなければならないため、素粒子のプリミティブを使用することはお勧めできません。ミューテックスを使用して
はOK行くスタイルです - あなたは非常に簡単にロックすると、現在のポインタを返すように関数を定義することができ、例えば
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()
}
のようなもの
これらの機能がどの意志顧客へのポインタのコピーを返しますマスターポインタが変更されても一定に保たれます。これは、あなたの要件がどのように時間的に重要であるかに応じて、受け入れ可能である場合もあります。未定義の動作を避けるだけで十分です。ガベージコレクタは、指されたメモリがプログラムによって使用されなくなっても、ポインタが常に有効であることを保証します。
代わりのアプローチは、1つのgoルーチンからのポインタアクセスのみを行い、チャネルを使用してルーチンを実行するように指示することです。それはもっと慣れ親しんだものと見なされますが、あなたのアプリケーションに正確に適合しないかもしれません。
Here is an example atomic.SetPointerの使い方を示しています。安全ではないため、むしろ醜いです。ただし、安全でない。ポインタのキャストは何もコンパイルされないため、ランタイムコストは小さい。
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))
}
いいえ、唯一のアトミック操作は 'sync/atomic'です。常に読み書きを同期させる必要があります。 – JimB
[参照](http://stackoverflow.com/q/41406501/720999)。 – kostix