2017-04-15 5 views
0

次のコードに競合状態がある理由がわかりません。誰かが私にヒントを与えることができますか?潜在的な競争状態はないと私は思う。前もって感謝します。go言語の潜在的な競合状態

type PossiblySafeCounter struct { 
    mu sync.Mutex 
    sum int 
} 

func (c *PossiblySafeCounter) inc() { 
    c.mu.Lock(); 
    defer c.mu.Unlock(); 
    go func() { 
     c.sum++ 
    }() 
} 
func (c *PossiblySafeCounter) read() int { 
    c.mu.Lock(); 
    defer c.mu.Unlock(); 
    return c.sum 
} 
+1

なぜあなたはそれがあると思いますか? – Carcigenicate

答えて

6

c.sum++は独立inc()方法の実行のスケジュールさゴルーチンです。 inc()メソッドが終了すると、mutexのロックが解除され、間違ったタイミングで競合が発生する可能性が非常に高くなります。

@Flimzyは、atomic.AddInt32を使用すると、ミューテックスの必要性が全くなくなることを示唆しています。

func (c *PossiblySafeCounter) inc() { 
    c.mu.Lock(); 
    defer c.mu.Unlock(); 
    c.sum++ 
} 

またはロックとにゴルーチンをロック解除の操作を行います:

2つのミューテックスベースのソリューションは、ゴルーチンでインクリメントしないようにされているか、のいずれかの種類をやって、

func (c *PossiblySafeCounter) inc() { 
    go func() { 
     c.mu.Lock(); 
     defer c.mu.Unlock(); 
     c.sum++ 
    }() 
} 

正直なところをこの例では、ゴルーチンは意味をなさない。なぜあなたは増分をゴルーチンに入れる必要がありますか?

+0

私たちが同じことを考えているかどうかはわかりません。直ちにロックを解除し、読み取りの前にロックを取得すると、ゴルーチンが合計を変更することができますか? – vkosyj

+2

実際の 'c.sum ++'がgoroutineで起こっているという事実は、mutexがインクリメントに関係することを何も保護していないことを意味します。 –

+2

より良い解決策は、['atomic.AddInt32'](https://golang.org/pkg/sync/atomic/#AddInt32)を使用してロックを必要としないことです。 – Flimzy