Go 快速入门指南 - 原子操作

概述

调用 sync/atomic 包即可。

错误的并发操作

先来看一个错误的示例。

通过启动 1000 个 goroutine 来模拟并发调用,在函数内部对变量 number 进行自增操作,那么可能存在的一个问题是,当多个 goroutine 同时对变量操作时,只有一个成功了,其他的全部失败,造成的后果就是变量最终的值小于 1000 (正常情况应该是等于 1000)。

package main

import (
    "fmt"
    "sync"
)

func main() {
    var number uint32
    var wg sync.WaitGroup

    for i := 0; i < 1000; i++ {
        wg.Add(1)

        go func() {
            defer func() {
                wg.Done()
            }()

            number++
        }()
    }

    wg.Wait()

    fmt.Printf("number = %d\n", number)
}

// $ go run main.go
// 输出如下,你的输出可能和这里的不一样,多试几次,会发现每次的结果都不一样
/**
  number = 971
*/

正确的并发操作

package main

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

func main() {
    var number uint32
    var wg sync.WaitGroup

    for i := 0; i < 1000; i++ {
        wg.Add(1)

        go func() {
            defer func() {
                wg.Done()
            }()

            //number++
            atomic.AddUint32(&number, 1) // 使用原子操作
        }()
    }

    wg.Wait()

    fmt.Printf("number = %d\n", number)
}

// $ go run main.go
// 输出如下,多试几次,会发现结果都是一样的
/**
  number = 1000
*/

联系我

公众号

go
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 2

这个地方用互斥锁是不是一样的,

mu.Lock()
number++
mu.Unlock()
1年前 评论
洋芋土豆 (楼主) 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!