1. ホーム
  2. go

[解決済み] RWMutexの使い方は?

2023-07-20 22:53:59

質問

type Stat struct {
    counters     map[string]*int64
    countersLock sync.RWMutex
    averages     map[string]*int64
    averagesLock sync.RWMutex
}

以下のように呼び出されます。

func (s *Stat) Count(name string) {
    s.countersLock.RLock()
    counter := s.counters[name]
    s.countersLock.RUnlock()
    if counter != nil {
        atomic.AddInt64(counter, int64(1))
        return
    }
}

私の理解では、まず受信者 s (これは型 Stat) をロックし、次にカウンターが存在する場合にそれに追加します。

質問です。

Q1:なぜロックする必要があるのでしょうか?また RWMutex は何を意味するのですか?

Q2: s.countersLock.RLock() - は、受信機全体をロックするのでしょうか、それとも Stat 型のカウンタフィールドのみをロックするのでしょうか?

Q3: s.countersLock.RLock() - は、平均値フィールドをロックしてしまうのでしょうか?

Q4: なぜ RWMutex ? Golangでは並行処理を行うにはチャネルを使うのが望ましいと思っていたのですが?

Q5: この atomic.AddInt64 . この場合、なぜatomicが必要なのでしょうか?

Q6:なぜ追加する直前にロックを解除するのでしょうか?

どのように解決するのですか?

<ブロッククオート

質問です。

Q1:なぜロックする必要があるのでしょうか?また RWMutex は何を意味するのですか?

RWはRead/Writeの略です。CFのドキュメントです。 http://golang.org/pkg/sync/#RWMutex .

処理中に他のルーチンやスレッドが値を変更するのを防ぐためにロックする必要があります。

Q2: s.countersLock.RLock() - は、受信機全体がロックされるのでしょうか? をロックするのでしょうか、それとも Stat 型のカウンタフィールドのみをロックするのでしょうか?

ミューテックスとして、ロックが発生するのは RLock() 関数を呼び出したときだけです。もし他のゴルーチンがすでに WLock() を既に呼んでいれば、ブロックされる。をいくつでも呼び出すことができます。 RLock() をいくつでも呼び出せますが、ロックされません。

ですから、他のフィールドをロックすることはありませんし s.counters . あなたの例では、正しいカウンターを見つけるためにマップの検索をロックしています。

Q3: s.countersLock.RLock() - は、平均値フィールドをロックしてしまうのでしょうか?

いいえ、Q2で述べたように RLock は自分自身をロックしているだけです。

Q4: なぜ RWMutex ? 私はチャネルがGolangで並行処理を行うための好ましい方法だと考えていました。 を使うべきだと思いましたか?

チャネルはとても便利ですが、時には十分ではなく、意味をなさないこともあります。

ここでは、マップのアクセスをロックするように、mutexが意味を持ちます。ちゃんねるでは、1のバッファリングされたちゃんねるを持ち、前に送信し、後に受信しなければならないでしょう。あまり直感的ではありません。

Q5: これは何ですか? atomic.AddInt64 . この場合、なぜatomicが必要なのでしょうか?

この関数は、与えられた変数をアトミックにインクリメントします。あなたの場合、レースコンディションが発生しています。 counter はポインタであり、実際の変数はロックが解除された後かつ atomic.AddInt64 . もしあなたがこの種のことに精通していないなら、私はMutexに固執し、ロック/アンロックの間に必要なすべての処理を行うことをお勧めします。

Q6:なぜ追加する直前にロックを解除するのでしょうか?

やめたほうがいいです。

何をしようとしているのか分かりませんが、(簡単な)例を挙げます。 https://play.golang.org/p/cVFPB-05dw