Concurrency Coordination Reports
RWMutex Read Coordination Report
Record shared read guards against a write probe and report the read status.
shared reads
`sync.RWMutex.TryRLock` grants multiple read locks at once, so several readers can hold the lock together. A `TryLock` write probe is rejected while any read lock is held, so the report shows the write as blocked. The number of live read locks drives the coordination status from writable through single to shared.
RWMutex Read Coordination Report
rwmutex_read_coordination_report.go
Replay: real traced execution (multi-file project)
package main
import (
"fmt"
"sync"
)
func main() {
var readers = 2
var lock sync.RWMutex
active := 0
for i := 0; i < readers; i++ {
ok := lock.TryRLock()
if ok {
active++
}
}
wok := lock.TryLock()
writeBlocked := !wok
var status string
if active == 0 {
status = "writable"
} else if active == 1 {
status = "single"
} else {
status = "shared"
}
fmt.Printf("readers=%d write_blocked=%t %s\n", active, writeBlocked, status)
}
package main
import (
"fmt"
"sync"
)
func main() {
var readers = 0
var lock sync.RWMutex
active := 0
for i := 0; i < readers; i++ {
ok := lock.TryRLock()
if ok {
active++
}
}
wok := lock.TryLock()
writeBlocked := !wok
var status string
if active == 0 {
status = "writable"
} else if active == 1 {
status = "single"
} else {
status = "shared"
}
fmt.Printf("readers=%d write_blocked=%t %s\n", active, writeBlocked, status)
}
package main
import (
"fmt"
"sync"
)
func main() {
var readers = 1
var lock sync.RWMutex
active := 0
for i := 0; i < readers; i++ {
ok := lock.TryRLock()
if ok {
active++
}
}
wok := lock.TryLock()
writeBlocked := !wok
var status string
if active == 0 {
status = "writable"
} else if active == 1 {
status = "single"
} else {
status = "shared"
}
fmt.Printf("readers=%d write_blocked=%t %s\n", active, writeBlocked, status)
}
readers ← 2, lock ← sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:0}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}
8func main() {9 var readers→ 2 = 2 //@readers=0, 110 var lock→ sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:0}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}} sync.RWMutex11 active→ 0 := 012 for i := 0; i < readers; i++ {lock ← sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:1}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}
pass 1 of 211active := 012for i0 := 0; i < readers2; i++ {13 ok→ true := lock→ sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:1}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}.TryRLock()14 if ok {active ← 1
pass 1 of 213ok := lock.TryRLock()14if oktrue {15 active→ 1++16}lock ← sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:2}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}
pass 2 of 211active := 012for i1 := 0; i < readers2; i++ {13 ok→ true := lock→ sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:2}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}.TryRLock()14 if ok {active ← 2
pass 2 of 213ok := lock.TryRLock()14if oktrue {15 active→ 2++16}wok ← false, writeBlocked ← true, status ← ""
17}18wok→ false := locksync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:2}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}.TryLock()19writeBlocked→ true := !wokfalse20var status→ "" string21if active == 0 {status ← "shared"
24 status = "single"25} else {26 status→ "shared" = "shared"27}fmt.Printf("readers=%d write_blocked=%t %s ", active, writeBlocked, st…
27 }28 fmt.Printf("readers=%d write_blocked=%t %s\n", active2, writeBlockedtrue, status"shared")29}outputreaders=2 write_blocked=true shared
readers ← 0, lock ← sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:0}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}
8func main() {9 var readers→ 0 = 010 var lock→ sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:0}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}} sync.RWMutex11 active→ 0 := 012 for i := 0; i < readers; i++ {13 ok := lock.TryRLock()14 if ok {15 active++16 }17 }18 wok→ true := lock→ sync.RWMutex{w:sync.Mutex{state:1, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:-1073741824}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}.TryLock()19 writeBlocked→ false := !woktrue20 var status→ "" string21 if active == 0 {status ← "writable"
20var status string21if active0 == 0 {22 status→ "writable" = "writable"23} else if active == 1 {fmt.Printf("readers=%d write_blocked=%t %s ", active, writeBlocked, st…
27 }28 fmt.Printf("readers=%d write_blocked=%t %s\n", active0, writeBlockedfalse, status"writable")29}outputreaders=0 write_blocked=false writable
readers ← 1, lock ← sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:0}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}
8func main() {9 var readers→ 1 = 110 var lock→ sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:0}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}} sync.RWMutex11 active→ 0 := 012 for i := 0; i < readers; i++ {lock ← sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:1}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}
11active := 012for i0 := 0; i < readers1; i++ {13 ok→ true := lock→ sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:1}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}.TryRLock()14 if ok {active ← 1
13ok := lock.TryRLock()14if oktrue {15 active→ 1++16}wok ← false, writeBlocked ← true, status ← ""
17}18wok→ false := locksync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:1}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}.TryLock()19writeBlocked→ true := !wokfalse20var status→ "" string21if active == 0 {status ← "single"
22 status = "writable"23} else if active1 == 1 {24 status→ "single" = "single"25} else {fmt.Printf("readers=%d write_blocked=%t %s ", active, writeBlocked, st…
27 }28 fmt.Printf("readers=%d write_blocked=%t %s\n", active1, writeBlockedtrue, status"single")29}outputreaders=1 write_blocked=true single