Go学习笔记—原子计算器

Go学习笔记—原子计算器、互斥锁、Go状态协程


1、原子计算器atomic-counters

状态管理方式除了通过通道间的沟通完成,还可以使用原子计算的方法。

原子计算在sync/atomic包中。通过调用即可使用。

func main(){
    var ops uint64 = 0 // 定义一个计数器
    for i:=0;i<50;i++{
        go func() {
            for{
                atomic.AddUint64(&ops,1) // 进行一次加一操作

                runtime.Gosched() // 不影响其他协程的运行
            }
        }()
    }
    time.Sleep(time.Second) // 模拟间隔时间

    opsFinal := atomic.LoadUint64(&ops) // 为了计数器被其他协程更新时,安全使用,可以使用拷贝的方法将计数器中的值拷贝出来
    fmt.Println("ops:",opsFinal)
}
2、互斥锁mutexes

可以使用互斥锁在goroutine中安全的获取数据。

func main(){
    
    var state = make(map[int]int)	// 定义一个map
    var mutex = &sync.Mutex{}	// 定义一个锁对象
    var ops int64 = 0	// 定义一个计数器,记录对state的操作

    for r:=0;r<100;r++{
        go func() {
            total := 0
            for {
                key := rand.Intn(5)	// 随机获取key的值
                mutex.Lock()	// 打开锁
                total += state[key]	// 将state的值传给total
                mutex.Unlock()	// 关闭锁
                atomic.AddInt64(&ops,1)	// 计数器+1
                runtime.Gosched()	// 保证不出现锁饿死的现象
            }
        }()
    }

    for w:=0;w<10;w++{
        go func() {
            key := rand.Intn(5)	// 随机获取key的值
            val := rand.Intn(100)	// 随机获取val的值
            mutex.Lock()	// 打开锁
            state[key] = val	// 给state赋值
            mutex.Unlock()	// 关闭锁
            atomic.AddInt64(&ops,1)	// 计数器+1
            runtime.Gosched()	// 保证不出现死锁情况
        }()
    }
    time.Sleep(time.Second)	// 模拟间隔时间

    opsFinal := atomic.LoadInt64(&ops)	// 获取ops的值
    fmt.Println("ops:",opsFinal)	// 输出ops的值

    mutex.Lock()	// 打开锁
    fmt.Println("state:",state)	// 输出state的值
    mutex.Unlock()	// 关闭锁
}
3、Go状态协程stateful-goroutins

使用goroutinechannel实现共享资源跨多个goroutine同步访问。

type readOp struct {
    key int
    resp chan int
}

type writeOp struct {
    key int
    val int
    resp chan bool
}

func main(){
    
    var ops int64	// 定义计数器
    reads := make(chan *readOp)	// 定义readOp类的通道
    writes := make(chan *writeOp)	// 定义writeOp类的通道

    go func() {		// 在协程中执行
        var state = make(map[int]int)	// 定义map
        for {
            select {	// 通道选择器
            case read := <- reads:	// 接收来自reads通道中的数据
                read.resp <- state[read.key]	// 向readOp的resp通道中发送数据
            case write := <- writes:	// 接收来自writes通道中的数据
                state[write.key] = write.val	// 键值对复制
                write.resp <- true	// 向writeOp的resp通道中发送数据
            }
        }
    }()
    
    for r:=0;r<100;r++{	// 模拟在readOp中操作
      go func() {
          for {
              read := &readOp{	// 创建实例
                  key: rand.Intn(5),
                  resp: make(chan int),
              }
              reads <- read	// 向reads通道中发送数据
              <- read.resp	// 接收数据
              atomic.AddInt64(&ops,1)	// 计数器+1,
          }
      }()
    }
    time.Sleep(time.Second)	// 协程运行1秒

    opsFinal1 := atomic.LoadInt64(&ops)	// 获取计数器的值,协程运行的次数
    fmt.Println("ops1:",opsFinal1)

    for w:=0;w<10;w++{
       go func() {
           for {
               write := &writeOp{	// 创建实例
                   key: rand.Intn(5),
                   val: rand.Intn(5),
                   resp:make(chan bool),
               }
               writes <- write	// 向writes通道发送数据
               <-write.resp	// 接收数据
               atomic.AddInt64(&ops,1) // 计数器+1
           }
       }()
    }
    time.Sleep(time.Second)	// 协程运行1秒


    opsFinal2 := atomic.LoadInt64(&ops)	// 获取计数器的值,协程运行的次数
    fmt.Println("ops2:",opsFinal2)
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值