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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- sync.Mutexとsync.RWMutex
- sync.WaitGroup
- sync.Onceとsync.Map
- 競合検出器と安全なパターン