2016-08-15 10 views
5

私はスレッドセーフなアクセスにはcountプロパティが必要です。このスレッドセーフな並行アクセスですか?

sync.Mutexまたはsync.RWMutexとすることができます。しかし、私はこのように大丈夫だとは分かりません:

type Status struct { 
    count uint32 

    attr1 string 
    attr2 string 
} 

func (s *Status) Get() uint32 { 
    return atomic.LoadUint32(&s.count) 
} 

func (s *Status) Add(n uint32) { 
    atomic.AddUint32(&s.count, n) 
} 

func (s *Status) Reset(n uint32) { 
    atomic.StoreUint32(&s.count, n) 
} 

ありがとう。

編集:

私がアクセスフィールドが直接s.count安全ではないことを混乱しています。しかしatomic.LoadUint32(&s.count)は安全ですか?

+0

任意の言語で任意のフィールドにアクセスすることは安全ではありません彼らのタイプのシステムPonyのように、またはRustのようないくつかの言語は、「提供する」とは並行アクセスを安全にすることを意味します。したがって、通常の/メインストリームのプログラミング言語を使用する場合は、常に安全であるとみなす必要があります。 –

答えて

3

はい、これらの3つのメソッドだけがcountフィールドにアクセスする場合、ソリューションは複数のゴルーチンから同時に安全に使用できます。

しかし、Status.Get()によって返される値は、使用しようとすると「古い」ことがあります。例えば:s.Get()と第2の呼を別のゴルーチンでs.Add()に別の呼び出しによって先行されるかもしれないよう

s := &Status{} 

if s.Get() == 3 { 
    fmt.Println(s.Get()) // This may or may not print 3 
} 

// Or 
c := s.Get() 
fmt.Println(c == s.Get()) // This may or may not print true 

上記の例では、又は3trueを印刷してもしなくてもよいです。

あなたはその誰もが他の修正を保証する必要があるか、あなたはそれにさらに計算を実行しながら、Status.countフィールドの値にアクセスする場合は、あなたながらcountフィールドのロックを保持できるよう、そしてsync.Mutexまたはsync.RWMutexは、移動するための方法でありますあなたの計算を完了してください。

編集:あなたの編集に答えるために:s.count

直接アクセスはatomic.LoadUint32(&s.count)が安全である、安全ではありません。なぜなら、ゴルーチン#1がs.Add()を呼び出し、ゴルーチン#2がs.countにアクセスしようとすると、#1の変更がゴルーチン#2に反映されるという保証はないからです。 #2では、キャッシュされたバージョンのs.countが表示されます。

明示的な同期がなければ、別のゴルーチンの変数に加えられた変更を確認することはできません。 s.countに直接アクセスすると、非同期アクセスになります。チャネルまたはその他の同期プリミティブ(syncまたはsync/atomicパッケージなど)を使用すると、s.countにシリアル化されたアクセスが保証されるため、これらのソリューションには現在の最新の値が常に表示されます。詳細について

は、こちらの記事を参照: - 多分アーランとエリクサーやHaskellのようないくつかの純粋な関数型言語またはの一部として、並行性を考慮した複合型システムを持っているいくつかの言語を除くThe Go Memory Model

関連する問題