web-dev-qa-db-ja.com

Goの構造体にミューテックスを埋め込むのはいつですか?

注:タイトルに「埋め込み」という単語を使用するのは不適切な選択でしたが、そのままにしておきます。

私は多くのコードがこのようになっているのを見ます:

type A struct {
    mu sync.Mutex
    ...
}

そして、次のように使用します。

a := &A{}

a.mu.Lock()
defer a.mu.Unlock()

a.Something()

ローカルミューテックスまたはグローバルミューテックスよりも優れていますか?

a := &A{}

var mu sync.Mutex
mu.Lock()
defer mu.Unlock()

a.Something()

前者をいつ使うべきですか、それとも後で使うべきですか?

8
kim yong bin

ミューテックスを保護する予定のデータに近づけることをお勧めします。ミューテックスが構造体値のフィールドへの同時アクセスを保護する必要がある場合、その構造体のフィールドとしてミューテックスを追加すると非常に便利なので、その目的は明らかです。

アプリにAの「インスタンス」が1つしかない場合は、ミューテックスをグローバル変数にすることもできます。

アプリでAの複数の値を作成する場合、そのすべてを同時アクセスから保護する必要があります(ただし、個別にのみ、複数の値に同時にアクセスできます)。明らかに、グローバルミューテックスは不適切な選択です。同時アクセスを任意の時点でAの単一の値に制限します。

ミューテックスをフィールドとして構造体に追加すると、当然個別の構造体値ごとに個別のミューテックスが作成され、構造体値を含むその単一の構造体を保護する責任があります。 (またはそのフィールド)。

あなたの例のようにミューテックスを追加することは埋め込みではありませんが、それは通常の名前付きフィールドです。 埋め込みフィールド宣言 はフィールド名を省略します。

あまり知られておらず、あまり使用されていませんが、構造体にミューテックスを「本当に」埋め込むことができ、Lock()Unlock()をまるで呼び出すことができるのも便利です。構造体自体の一部。次のようになります。

var hits struct {
    sync.Mutex
    n int
}

hits.Lock()
hits.n++
hits.Unlock()

(この例は Goについて(おそらく)知らない10のこと、スライド# から抜粋したものです。)

30
icza