Concurrency in Go Chapter1 (6)
1 min readOct 1, 2017
“Concurrency in Go: Tools and Techniques for Developers”の1章 “An Introduction to Concurrency”の読書メモ。Livelockについて書く。
Livelock
Livelock are programs that are actively performing concurrent operaions, but these operations do not nothting to move the state of program forward.
前から歩いてきた人と同じ方向に避けてしまうことを何度も繰り返してしまい、前に進めない状況をイメージすればよい。
package mainimport (
"bytes"
"fmt"
"sync"
"sync/atomic"
"time"
)func main() {
cadence := sync.NewCond(&sync.Mutex{})
go func() {
for range time.Tick(1 * time.Millisecond) {
cadence.Broadcast()
}
}() takeStep := func() {
cadence.L.Lock()
cadence.Wait()
cadence.L.Unlock()
} tryDir := func(dirName string, dir *int32, out *bytes.Buffer) bool {
fmt.Fprintf(out, " %v", dirName)
atomic.AddInt32(dir, 1)
takeStep()
if atomic.LoadInt32(dir) == 1 {
fmt.Fprint(out, ". Success!")
return true
}
takeStep()
atomic.AddInt32(dir, -1)
return false
} var left, right int32
tryLeft := func(out *bytes.Buffer) bool {
return tryDir("left", &left, out)
}
tryRight := func(out *bytes.Buffer) bool {
return tryDir("right", &right, out)
} walk := func(walking *sync.WaitGroup, name string) {
var out bytes.Buffer
defer func() {
fmt.Println(out.String())
}()
defer walking.Done()
fmt.Fprintf(&out, "%v is trying to scoot:", name) for i := 0; i < 5; i++ {
if tryLeft(&out) || tryRight(&out) {
return
}
}
fmt.Fprintf(&out, "\n%v tosses her hands up in exasperation!", name)
} var peopleInHallway sync.WaitGroup
peopleInHallway.Add(2)
go walk(&peopleInHallway, "A")
go walk(&peopleInHallway, "B")
peopleInHallway.Wait()
}