doc.go

2019-03-28  本文已影响0人  killtl

概述

doc.go是包atomic的提供低级原子操作的实现,对于实现同步算法很有用
包含的原子操作有5种

支持的类型包含

增或减

被用于增或减的原子操作都是以Add为前缀,并在后面跟具体类型的名称,如

func AddUint32(addr *uint32, delta uint32) (new uint32)

示例

package main

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

func main() {
    var wg sync.WaitGroup
    var i,j int32 = 0,0

    wg.Add(20)

    for n := 10; n > 0; n-- {
        go func() {
            defer wg.Done()

            for n := 1000; n > 0; n-- {
                i++
            }
        }()

        go func() {
            defer wg.Done()

            for n := 1000; n > 0; n-- {
                atomic.AddInt32(&j, 1)
            }
        }()
    }

    wg.Wait()

    fmt.Println(i, j)
}

// output
9615 10000

看到了吧,并发数量高的时候,AddInt32可以保证原子性,保证结果正确,而减法的实现是通过加上一个负数

package main

import "sync/atomic"

func main() {
    var i int32 = 5
    atomic.AddInt32(&i, -10)
    print(i)
}

// output 
-5

交换

原子交换操作,这类函数的名称都以Swap为前缀,交换操作直接赋予新值,不管旧值

func SwapInt32(addr *int32, new int32) (old int32)

在原子性上等价于

old = *addr
*addr = new
return old

比较并交换

简称CAS操作(Compare And Swap),只有被操作的值未曾改变(即与旧值相等),则进行swap,这类函数名称都以CompareAndSwap为前缀

func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)

在原子性上等价于

if *addr == old {
    *addr = new
    return true
}
return false

载入

原子读取某个值,即在读取过程中不允许写操作,这类函数名称都以Load为前缀

func LoadInt32(addr *int32) (val int32)

在原子性上等价于

return *addr

存储

原子写操作,与载入刚好相反,即在写过程中不允许其他的读/写操作,这类函数名称都以Store为前缀

func StoreInt32(addr *int32, val int32)

在原子性上等价于

*addr = val
上一篇下一篇

猜你喜欢

热点阅读