0Pricing
Go Academy · レッスン

sync.Mutexとsync.RWMutex

ロックと読み書きロックのパターン

「sync.Mutexとsync.RWMutex」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

なぜMutexを使うのか

複数のゴルーチンが変更可能な状態を共有すると、同時読み取りや同時書き込みによってデータ競合が発生します。Mutex はアクセスを直列化し、一度に1つのゴルーチンだけがクリティカルセクションに入れるようにします。

sync.Mutexの基本

共有状態を読み取る、または書き込む前に Lock を呼び出し、その後に Unlock を呼び出します。関数がパニックしても確実にロックを解除できるよう、defer を使用します。

var mu sync.Mutex
var counter int

func inc() {
    mu.Lock()
    defer mu.Unlock()
    counter++
}

構造体へのMutexの埋め込み

保護対象の構造体に Mutex を埋め込みます。慣例として、Mutex は保護するフィールドのすぐ上に宣言します。

type SafeCounter struct {
    mu sync.Mutex
    v  map[string]int
}
func (c *SafeCounter) Inc(key string) {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.v[key]++
}

Mutexをコピーしない

Mutex は初回使用後にコピーしてはいけません。ポインターで渡すか、ポインターで渡される構造体に埋め込みます。go vet ツールでコピーを検出できます。

sync.RWMutex

sync.RWMutex は複数の読み取りを同時に許可しますが、書き込みは一度に1つだけ許可します。読み取りが多く、書き込みが少ない場合に使用すると、スループットを向上できます。

var rw sync.RWMutex
var data map[string]int

func read(k string) int {
    rw.RLock()
    defer rw.RUnlock()
    return data[k]
}
func write(k string, v int) {
    rw.Lock()
    defer rw.Unlock()
    data[k] = v
}

RLockとLockの違い

RLock は読み取りロック(共有)を取得し、Lock は書き込みロック(排他的)を取得します。書き込みロックが待機中の場合、新しい読み取りロックをブロックして、書き込み側の飢餓を防ぎます。

TryLock(Go 1.18以降)

mu.TryLock() は、現在ロックが解除されている場合にのみロックを取得し、真偽値を返します。ブロックが許容できない場合に便利です。

if mu.TryLock() {
    defer mu.Unlock()
    // critical section
}

デッドロック

デッドロックは、ゴルーチン A がロック1を保持したままロック2を待機し、ゴルーチン B がロック2を保持したままロック1を待機すると発生します。常に同じ順序でロックを取得し、クリティカルセクションを短く保ちます。

ロックの粒度

粗い粒度のロックは理解しやすい一方で、並行性を低下させます。細かい粒度のロックはスループットを向上させますが、複雑さとデッドロックのリスクが増加します。まずは粗い粒度で実装し、プロファイリングで競合が確認された場合に最適化します。

Mutexとチャネルの比較

多数の読み取り側や書き込み側から共有状態を保護する場合は Mutex を使用します。ゴルーチン間でデータの所有権を移す場合はチャネルを使用します。チャネルは通信に、Mutex は同期に使用します。

sync.Lockerインターフェース

sync.Locker は Lock と Unlock を持つインターフェースです。Mutex と RWMutex はどちらもこれを実装しているため、ヘルパー関数でどちらの型も受け取れます。

確認問題

sync.RWMutexは、sync.Mutexの代わりにどのような場合に使用すべきでしょうか。

まとめ: MutexとRWMutex

要点:

  • Mutexはアクセスを直列化します。Unlockは必ずdeferします
  • 一度使用したMutexをコピーしてはいけません
  • RWMutexでは、複数の読み取りまたは1つの書き込みを同時に実行できます
  • デッドロックを避けるため、ロックを一貫した順序で取得します

よくある質問

「sync.Mutexとsync.RWMutex」レッスンは無料ですか?

はい。「sync.Mutexとsync.RWMutex」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「sync.Mutexとsync.RWMutex」で何を学びますか?

ロックと読み書きロックのパターン ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「sync.Mutexとsync.RWMutex」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. sync.Mutexとsync.RWMutex
  2. sync.WaitGroup
  3. sync.Onceとsync.Map
  4. 競合検出器と安全なパターン
← Go Academyに戻る