Go语言中atomic包的应用

2018-05-16  本文已影响0人  坤_7a1e

sync/atomic包提供了原子操作的能力,直接有底层CPU硬件支持,因而一般要比基于操作系统API的锁方式效率高些;

这些功能需要非常小心才能正确使用。 除特殊的底层应用程序外,同步更适合使用channel或sync包的功能。 通过消息共享内存; 不要通过共享内存进行通信。

原子增值

    我们通过下面用例来了解下,原子增值跟普通增值的不同

        package main

        import (

        "fmt"

        "sync/atomic"

        "sync"

        )

        func main() {

            var sum uint32 = 200

            var wg sync.WaitGroup

            for i:=0; i< 30; i++ {

                wg.Add(1)

                go func() {

                    defer wg.Done()

                    atomic.AddUint32(&sum, 1)

                }()

            }

            wg.Wait()

            fmt.Println(sum)

            for i:=0; i< 30; i++ {

                wg.Add(1)

                go func() {

                    defer wg.Done()

                    sum++

                }()

            }

            wg.Wait()

            fmt.Println(sum)

    }

    将上面程序在工作机上编译,然后运行几次,你会发现第一个打印值固定不变,第二个值不固定

CAS(Compare-And-Swap)比较并交换

func CompareAndSwapInt32(addr *int32, old, newint32) (swappedbool)

下面代码体现了三种情况:

    a.当addr地址指向变量的值不等于old

    b.当addr地址指向变量的值等于old,等于new

    c.当addr地址指向的变量值等于old,不等于new

    import (

        "fmt"

        "sync/atomic"

        "sync"

    )

    func main() {

        sum := uint32(10)

        rst := false

        var wg sync.WaitGroup

        for i := 0; i < 10; i++ {

        wg.Add(1)

        go func() {

            defer wg.Done()

            rst = atomic.CompareAndSwapUint32(&sum, 100, 200)

        }()

    }

    wg.Wait()

    fmt.Println(sum)

    fmt.Println(rst)

    rst1 := false

    sum1 := uint32(100)

    for i := 0; i < 10; i++ {

        wg.Add(1)

        go func() {

            defer wg.Done()

            rst1 = atomic.CompareAndSwapUint32(&sum1, 100, 100)

        }()

      }

    wg.Wait()

    fmt.Println(sum1)

    fmt.Println(rst1)

    rst2 := false

    sum2 := uint32(100)

    for i := 0; i < 10; i++ {

        wg.Add(1)

        go func() {

            defer wg.Done()

            rst2 = atomic.CompareAndSwapUint32(&sum2, 100, 200)

        }()

    }

    wg.Wait()

    fmt.Println(sum2)

    fmt.Println(rst2)

}

运行结果:

    10

    false

    100

    true

    200    

    false

原子导出值

    package main

    import (

        "fmt"

        "sync/atomic"

        "sync"

    )

    func main() {

        sum := uint32(1020)

        rst := uint32(0)

        var wg sync.WaitGroup

        for i := 0; i < 10; i++ {

                wg.Add(1)

                go func() {

                        defer wg.Done()

                        rst = sum

                }()

        }

        wg.Wait()

        fmt.Println(sum)

        fmt.Println(rst)

 }

原子导入值

package main

import (

        "fmt"

        "sync/atomic"

        "sync"

)

func main() {

        rst := uint32(0)

        var wg sync.WaitGroup

        for i := 0; i < 10; i++ {

                wg.Add(1)

                go func() {

                        defer wg.Done()

                        atomic.StoreUint32(&rst, 160)

                }()

        }

        wg.Wait()

        fmt.Println(rst)

}

原子交互

package main

import (

        "fmt"

        "sync/atomic"

        "sync"

)

func main() {

        rst := uint32(0)

        old := uint32(0)

        old = atomic.SwapUint32(&rst,  1234)

        fmt.Println(rst)

        fmt.Println(old)

        var wg sync.WaitGroup

        for i := 0; i < 10; i++ {

                wg.Add(1)

                go func() {

                        defer wg.Done()

                        old = atomic.SwapUint32(&rst,  1234)

                }()

        }

        wg.Wait()

        fmt.Println(rst)

        fmt.Println(old)

}

运行结果

    1234

    0

    1234

    1234

上一篇下一篇

猜你喜欢

热点阅读