2016-12-14 2 views
1

Ich habe ein einfaches Paket, das ich verwende, um Statistiken während eines Programmlaufs zu loggen, und ich fand, dass go run -race sagt, dass es eine Wettlaufbedingung darin gibt. Wenn ich mir das Programm anschaue, bin ich mir nicht sicher, wie ich eine Wettlaufsituation haben kann, wenn jedes Lesen und Schreiben durch einen Mutex geschützt ist. Kann jemand das erklären?Golang Rennen mit sync.Mutex auf Karte [string] int

package counters 

import "sync" 

type single struct { 
    mu  sync.Mutex 
    values map[string]int64 
} 

// Global counters object 
var counters = single{ 
    values: make(map[string]int64), 
} 

// Get the value of the given counter 
func Get(key string) int64 { 
    counters.mu.Lock() 
    defer counters.mu.Unlock() 
    return counters.values[key] 
} 

// Incr the value of the given counter name 
func Incr(key string) int64 { 
    counters.mu.Lock() 
    defer counters.mu.Unlock() 
    counters.values[key]++  // Race condition 
    return counters.values[key] 
} 

// All the counters 
func All() map[string]int64 { 
    counters.mu.Lock() 
    defer counters.mu.Unlock() 
    return counters.values  // running during write above 
} 

Ich benutze das Paket wie folgt:

counters.Incr("foo") 
counters.Get("foo") 

Antwort

1

All gibt die zugrunde liegende Karte zurück und gibt die Sperre frei, sodass der Code, der die Karte verwendet, ein Datenrennen hat.

Sie sollten eine Kopie der Karte zurück:

func All() map[string]int64 { 
    counters.mu.Lock() 
    defer counters.mu.Unlock() 
    m := make(map[string]int64) 
    for k, v := range counters.values { 
     m[k] = v 
    } 
    return m  
} 

Oder keine All Methode haben.

2

A Minimal komplettes Nachweisbare Beispiel wäre hier hilfreich sein, aber ich denke, Ihr Problem in All() ist:

// All the counters 
func All() map[string]int64 { 
    counters.mu.Lock() 
    defer counters.mu.Unlock() 
    return counters.values  // running during write above 
} 

Dies gibt eine map, die keine Kopie davon macht, so dass es außerhalb des Schutzes des Mutex zugegriffen werden kann.

Verwandte Themen