📝 Compare And Swap
● Mutexをアクセス制御する
リソースにつき1つ作成
● それを複数のgoroutineが
参照する
resource
G
Mutex
✅
❌
❌
G
G
変数の値の更新が競合しないようにatomicな操作で更新
https://pkg.go.dev/sync/atomic#pkg-overview
goroutine実行過程の概要
X := 3
pow(x)
P
G G
M G
G (goroutine): goroutine本体
P (Prosessor): 論理プロセッサ
M (Machine): OSスレッド
Inspired by
https://speakerdeck.com/sakiengineer/sukeziyurakaraxue-bugorantaimu-code-reading-of-runtime-pkg
Slide 48
Slide 48 text
goroutine実行過程の概要
X := 3
pow(x)
P
G G
M G
実行待ちのgoroutineを貯めるqueue
実行中のgoroutine
Slide 49
Slide 49 text
goroutine実行過程の概要
fmt.Println(“Hello”)
P
G G
M G
実行待ちのgoroutineがqueueから取り出され、逐次実行される
Slide 50
Slide 50 text
G
semacquire1(): harder case
sudog を用意
P
G G
M G
G
src/runtime/sema.go
Slide 51
Slide 51 text
● 待ち行列を表現するための構造体
● チャネルの内部実装にも使われる
sudog
G
prev addr next addr
src/runtime/runtime2.go
Slide 52
Slide 52 text
● semtableからsemaのアドレスを元に、rootノードを取得
semacquire1(): harder case
src/runtime/sema.go
Slide 53
Slide 53 text
semtable
Mutex
Mutex
G G G
G G
各Mutexをロックしようと待機している goroutineの待ち行列
「各Mutexのsemaをロック状態に更新しようと待機する
goroutineの待ち行列」の集合
G
Mutex
Mutex
G G
G
sematable (semaRootの配列)
src/runtime/sema.go
Slide 54
Slide 54 text
semacquire1(): harder case
P
G G
M G
G
Mutex
Mutex
G G
G
Mutexのsemaをロック状態に更新しよ
うと待機するgoroutineの待ち行列の先
頭ノードを取得!!
G
src/runtime/sema.go
Slide 55
Slide 55 text
semacquire1(): harder case
● semaをロック状態に更新しようと試みる
src/runtime/sema.go
Slide 56
Slide 56 text
semacquire1(): harder case
● この段階でロック状態に更新できない場合は、
現状ロックを取得できない状態と判断
=> ロック更新を一時停止し、goroutineをsleepさせるフェーズへ
src/runtime/sema.go
Slide 57
Slide 57 text
semacquire1(): goroutineの一時停止
P
G G
M G
G
G
G
Mutex
現在実行中のgoroutineを待ち行列に追加
src/runtime/sema.go