diff --git a/30-coordination/coordination/main.go b/30-coordination/coordination/main.go index 12e0629..006813d 100644 --- a/30-coordination/coordination/main.go +++ b/30-coordination/coordination/main.go @@ -10,6 +10,7 @@ import ( func main() { main1() main2() + main3() } func doSum(count int, val *int, waitGroup *sync.WaitGroup, mutex *sync.Mutex) { @@ -39,13 +40,16 @@ func main1() { func calculateSquares(index, max, iterations int, r *rand.Rand, waitGroup *sync.WaitGroup, rwMutex *sync.RWMutex, squares map[int]int) { for i := 0; i < iterations; i++ { val := r.Intn(max) + // 读取锁 rwMutex.RLock() square, ok := squares[val] rwMutex.RUnlock() if ok { Printfln("%v %v RLock Cached value: %v = %v ", index, i, val, square) } else { + // 写锁,当没有读到时,开启写锁 rwMutex.Lock() + // 重新读取值,防止缓存被其他goroutine修改 if square, ok := squares[val]; !ok { squares[val] = int(math.Pow(float64(val), 2)) Printfln("%v %v Added value: %v = %v", index, i, val, squares[val]) @@ -72,5 +76,57 @@ func main2() { } waitGroup.Wait() Printfln("Cached Value: %v", len(squares)) - +} + +func generateSquares(max int, waitGroup *sync.WaitGroup, rwMutex *sync.RWMutex, readyCond *sync.Cond, squares map[int]int) { + // 开启写锁 + rwMutex.Lock() + // 重新读取值,防止缓存被其他goroutine修改 + Printfln("Generating data...") + for i := 0; i < max; i++ { + squares[i] = int(math.Pow(float64(i), 2)) + } + // 关闭写锁 + rwMutex.Unlock() + + // 读锁开始广播 + Printfln("Broadcasting condition") + readyCond.Broadcast() + waitGroup.Done() +} + +func readSquares(id, max, iterations int, r *rand.Rand, waitGroup *sync.WaitGroup, readyCond *sync.Cond, squares map[int]int) { + readyCond.L.Lock() + for len(squares) == 0 { + readyCond.Wait() + } + for i := 0; i < iterations; i++ { + key := r.Intn(max) + Printfln("#%v,%v Read Index: %v = %v ", id, i, key, squares[key]) + time.Sleep(time.Millisecond * 100) + } + readyCond.L.Unlock() + waitGroup.Done() +} + +func main3() { + Printfln("\nmain3:") + + var waitGroup = sync.WaitGroup{} + var rwMutex = sync.RWMutex{} + var readyCond = sync.NewCond(rwMutex.RLocker()) + var squares = map[int]int{} + + var r = rand.New(rand.NewSource(time.Now().UnixNano())) + numRoutines := 2 + for i := 0; i < numRoutines; i++ { + waitGroup.Add(1) + go readSquares(i, 10, 5, r, &waitGroup, readyCond, squares) + } + + waitGroup.Add(1) + go generateSquares(10, &waitGroup, &rwMutex, readyCond, squares) + + waitGroup.Wait() + Printfln("Cached Value: %v", len(squares)) }