• go语言从例子开始之Example36.互斥锁


    在前面的例子中,我们看到了如何使用原子操作来管理简单的计数器。对于更加复杂的情况,我们可以使用一个互斥锁来在 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 次操作。

    坐标: 上一个例子   下一个例子

     

  • 相关阅读:
    Python常用转换函数
    Python随机数
    sublime text的pylinter插件设置pylint_rc后提示错误
    使用Pydoc生成文档
    字符编码笔记:ASCII,Unicode和UTF-8
    Windows编程MessageBox函数
    魔方阵算法及C语言实现
    iOS通讯录整合,兼容iOS789写法,附demo
    谈谈iOS app的线上性能监测
    ReactiveCocoa代码实践之-更多思考
  • 原文地址:https://www.cnblogs.com/yhleng/p/11771087.html
Copyright © 2020-2023  润新知