2017-02-24 4 views
-4

次のGo Playの例は、私が定義した単純な方法を示しています。私はコピーされた値として関数(参照ではない)としてマップを渡しているだけでなく、値渡しとみなす私の関数には再帰があります。並行性がない場合の同時マップ読み込みと書き込み

https://play.golang.org/p/na6y6Wih4M

// this function has no write operations to dataMap, just reads 
// dataMap, in fact, has no write operations since it was copied 
func findParentAncestors(ID int, dataMap map[int]Data) []Data { 
    results := []Data{} 
    if _, ok := dataMap[ID]; ok { 
     if parentData, ok := dataMap[dataMap[ID].ParentID]; ok { 
      results = append(results, parentData) 
      // recursion 
      results = append(results, findParentAncestors(parentData.ID, dataMap)...) 
     } 
    } 
    return results 
} 

問題:どういうわけか、この例よりもはるかに多くのデータを必要とする私のプログラムの実行、(obviusly)に沿って、エラー「致命的なエラー:同時マップ読み込み、マップ書き込み」ポイント機能findParentAncestors()

main.findParentAncestors(0x39e3, 0xc82013ac90, 0x0, 0x0, 0x0) 
    /opt/test/src/test.go:17 +0xa6 fp=0xc820269fb8 sp=0xc820269bd0 
main.findParentAncestors(0x5d25, 0xc82013ac90, 0x0, 0x0, 0x0) 
    /opt/test/src/test.go:21 +0x239 fp=0xc82026a3a0 sp=0xc820269fb8 
+0

Goのバージョンは?そのスタックトレースは完了していますか? – hobbs

+0

goバージョンgo1.6.3 linux/amd64 スタックトレースは、さまざまな並行通貨のため非常に大きくなります。中間の部分(パニックの一番上)が上記です。 dataMapは値渡しされます。私はこれが並行性の問題につながることはありません。 – gextra

+0

フルトレースをここに追加しましたhttps://play.golang.org/p/p75UITydPP – gextra

答えて

2

あなたの例から、https://play.golang.org/p/na6y6Wih4M

// the orignalMap is defined elsewhere in the program (here represented) 
originalMap := map[int]Data{} 
originalMap[0] = Data{ID: 0, ParentID: -1, Name: "zero"} 
originalMap[1] = Data{ID: 1, ParentID: 0, Name: "one"} 
originalMap[2] = Data{ID: 2, ParentID: 1, Name: "two"} 
// copies the original map from a global location (here represented) 
copiedMap := originalMap 
// identifies ancestors unsing the copied map 
parents := findParentAncestors(2, copiedMap) 

これは誤字であり、copiedMap := originalMapです。地図をコピーしていません。

Inすべての引数は値によって渡されます。各引数を各パラメータに割り当てるのと同じことです。マップの場合、copiedMap := originalMap、または値渡し、findParentAncestors(2, copiedMap)は、マップキー値データへのポインターを含むマップ記述子構造体へのポインターであるマップ記述子をコピーします。明らかに、マップへの書き込みがあれば、潜在的な競合状態になります。

go version go1.6.3 linux/amd64を使用していますので、レースディテクタを実行してください。また

Go 1.6 Release Notes

Runtime

The runtime has added lightweight, best-effort detection of concurrent misuse of maps. As always, if one goroutine is writing to a map, no other goroutine should be reading or writing the map concurrently. If the runtime detects this condition, it prints a diagnosis and crashes the program. The best way to find out more about the problem is to run the program under the race detector, which will more reliably identify the race and give more detail.

Command go

Compile packages and dependencies

-race 
    enable data race detection. 
    Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. 

、ゴー1.8、大幅同時マップの誤用を向上ゴーの現在のリリースを、使用してプログラムをコンパイルして実行します。

関連する問題