GO语言并发编程-原子操作

Posted sunansheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GO语言并发编程-原子操作相关的知识,希望对你有一定的参考价值。

引言

举一个例子, 将变量 n 从 0 开始, 自增 1000 次, 然而对于并发操作而言, 当两个或两个以上的 goroutines 同时读取内存中的 n 值, 然后将 n+1 的值放回内存,可能多次自增的结果,这个 n 只自增了 1 次!

这里需要使用原子操作, 以保证多个 goroutines 对同一块内存的操作是原子的, 即保证本例中 n 自增到最后的值为 1000.

示例

Go语言代码:

package main

import (
    "fmt"
    "sync"
    "sync/atomic"
)

func main() 
    var (
        wg     sync.WaitGroup
        nA, nB int64
    )

    wg.Add(2000)

    for i := 0; i < 1000; i++ 
        go func() 
            nA++
            wg.Done()
        ()
    
    for i := 0; i < 1000; i++ 
        go func() 
            atomic.AddInt64(&nB, 1)
            wg.Done()
        ()
    
    wg.Wait()
    fmt.Println(nA, nB)


输出结果:
963 1000

可以看到, 并发操作中, nA 的值不太可能自增到 1000, nB 使用了原子操作自增, 保证了每次自增都能成功.

sync.WaitGroup的用法

WaitGroup 对象内部有一个计数器,最初从0开始,它有三个方法:Add(), Done(), Wait() 用来控制计数器的数量。Add(n) 把计数器设置为n ,Done() 每次把计数器-1 ,wait() 会阻塞代码的运行,直到计数器地值减为0。

func main() 
    wg := sync.WaitGroup
    wg.Add(100)
    for i := 0; i < 100; i++ 
        go func(i int) 
            fmt.Println(i)
            wg.Done()
        (i)
    
    wg.Wait()

这里首先把wg 计数设置为100, 每个for循环运行完毕都把计数器减一,主函数中使用Wait() 一直阻塞,直到wg为零——也就是所有的100个for循环都运行完毕。

声明:Nansheng.Su 发表于 2019-05-13 14:41:27 ,共计276字。

转载请署名:GO语言并发编程-原子操作 | www.sunansheng.com

以上是关于GO语言并发编程-原子操作的主要内容,如果未能解决你的问题,请参考以下文章

Go语言自学系列 | golang并发编程之原子操作详解

Go并发编程之美-CAS操作

Go语言学习之旅--并发编程

Go语言学习之旅--并发编程

Go语言学习之旅--并发编程

Go 并发编程 — 结构体多字段的原子操作 atomic.Value