来源:https://github.com/xg-wang/gobyexample/tree/master/examples
//使用一个_[互斥锁]_在Go协程间安全的访问数据
package main
import (
"fmt"
"math/rand"
"runtime"
"sync"
"sync/atomic"
"time"
)
func main() {
var state = make(map[int]int)
//同步对`state`的访问
var mutex = &sync.Mutex{}
//记录操作次数
var ops int64 = 0
//运行100个Go协程来重复读取state
for r := 0; r < 100; r++ {
go func() {
total := 0
for {
key := rand.Intn(5)
//确保对`state` 的独占访问
mutex.Lock()
total += state[key]
mutex.Unlock()
atomic.AddInt64(&ops, 1)
//为了确保这个GO协程不会在调度中饿死,我们在每次操作后明确的使用
//`runtime.Gosched()`进行释放。这个释放一般是自动处理的,像例如
//每个通道操作后 或者`time.Sleep`的阻塞调用后相似。在此,我们需要手动处理
runtime.Gosched()
}
}()
}
//运行10个协程模拟写入操作
for w := 0; w < 10; w++ {
go func() {
for {
key := rand.Intn(5)
val := rand.Intn(100)
mutex.Lock()
state[key] = val
mutex.Unlock()
atomic.AddInt64(&ops, 1)
runtime.Gosched()
}
}()
}
//让上述操作运行2秒
time.Sleep(2 * time.Second)
//获取并输出最终的操作计数
opsFinal := atomic.LoadInt64(&ops)
fmt.Println("ops:", opsFinal)
//对`state`使用一个最终的锁,显示它是如何结束的
mutex.Lock()
fmt.Println("state:", state)
mutex.Unlock()
}
输出结果:
ops: 8126595
state: map[4:72 0:43 3:33 2:49 1:22]
网友评论