go语言从例子开始之Example36.互斥锁
2019-10-31 14:41 _天枢 阅读(295) 评论(0) 编辑 收藏 举报在前面的例子中,我们看到了如何使用原子操作来管理简单的计数器。对于更加复杂的情况,我们可以使用一个互斥锁来在 Go 协程间安全的访问数据。
Example:
package main import ( "fmt" "math/rand" "runtime" "sync" "sync/atomic" "time" ) func main() { //在我们的例子中,state 是一个 map。 var state = make(map[int]int) //这里的 mutex 将同步对 state 的访问。 var mutex = &sync.Mutex{} we'll see later, ops will count how manyoperations we perform against the state.为了比较基于互斥锁的处理方式和我们后面将要看到的其他方式,ops 将记录我们对 state 的操作次数。 var ops int64 = 0 //这里我们运行 100 个 Go 协程来重复读取 state。 for r := 0; r < 100; r++ { go func() { total := 0 for { //每次循环读取,我们使用一个键来进行访问,Lock() 这个 mutex 来确保对 state 的独占访问,读取选定的键的值,Unlock() 这个mutex,并且 ops 值加 1。 key := rand.Intn(5) mutex.Lock() total += state[key] mutex.Unlock() atomic.AddInt64(&ops, 1) //为了确保这个 Go 协程不会在调度中饿死,我们在每次操作后明确的使用 runtime.Gosched()进行释放。这个释放一般是自动处理的,像例如每个通道操作后或者 time.Sleep 的阻塞调用后相似,但是在这个例子中我们需要手动的处理。 runtime.Gosched() } }() } //同样的,我们运行 10 个 Go 协程来模拟写入操作,使用和读取相同的模式。 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() } }() } //让这 10 个 Go 协程对 state 和 mutex 的操作运行 1 s。 time.Sleep(time.Second) //获取并输出最终的操作计数。 opsFinal := atomic.LoadInt64(&ops) fmt.Println("ops:", opsFinal) //对 state 使用一个最终的锁,显示它是如何结束的。 mutex.Lock() fmt.Println("state:", state) mutex.Unlock() }
Result:
$ go run mutexes.go ops: 3598302 state: map[1:38 4:98 2:23 3:85 0:44]
运行这个程序,显示我们对已进行了同步的 state
执行了3,500,000 次操作。
作 者:
天枢
出 处:
http://www.cnblogs.com/yhleng/
关于作者:专注于软件自动化测试领域。如有问题或建议,请多多赐教!
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者
直接私信我
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角
【
推荐】
一下。您的鼓励是作者坚持原创和持续写作的最大动力!