go语言并发编程-原子操作(代码片段)

sunansheng sunansheng     2022-11-30     538

关键词:

引言

举一个例子, 将变量 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

2021-go语言并发编程

2021-GO语言并发编程1、Go语言并发概述2、GO语言多进程编程3、Go语言并发简略-多线程4、Go语言并发简略-非阻塞IO5、Go语言并发简略-协程6、并发简略-对比并发模型7、Go语言goroutine8、Go语言channel9、Go语言channel的操作10、Go语言channel... 查看详情

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

Go语言学习之旅--并发编程golang并发编程之协程golang并发编程之通道golang并发编程之WaitGroup实现同步golang并发编程之runtime包golang并发编程之Mutex互斥锁实现同步golang并发编程之channel的遍历golang并发编程之selectswitchgolang并发编程之T... 查看详情

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

Go语言学习之旅--并发编程golang并发编程之协程golang并发编程之通道golang并发编程之WaitGroup实现同步golang并发编程之runtime包golang并发编程之Mutex互斥锁实现同步golang并发编程之channel的遍历golang并发编程之selectswitchgolang并发编程之T... 查看详情

go并发编程(代码片段)

并发编程GoroutineGoroutine是Go语言特有的并发体,是一种轻量级的线程,由go关键字启动。在真实的Go语言的实现中,goroutine和系统线程也不是等价的。一个Goroutine会以一个很小的栈启动(可能是2KB或4KB),当遇到深度递归导致当前... 查看详情

云原生时代崛起的编程语言go并发编程实战(代码片段)

Go语言是天然并发利器,通过通信来实现内存共享而不是通过共享内存来通信,本篇从了解Go的并发哲学、理论及并发原语开始,之后用一个个Go代码示例认识Go的协程、通道、定时器、互斥锁、池化、原生操作等十几个并发编程... 查看详情

golang✔️走进go语言✔️第二十课原子操作&互斥体(代码片段)

【Golang】✔️走进Go语言✔️第二十课概述协程存在的问题原子操作互斥锁概述Golang是一个跨平台的新生编程语言.今天小白就带大家一起携手走进Golang的世界.(第20课)协程存在的问题当大量的协程并发的时候,会产生资源抢占冲突... 查看详情

golang✔️走进go语言✔️第二十课原子操作&互斥体(代码片段)

【Golang】✔️走进Go语言✔️第二十课概述协程存在的问题原子操作互斥锁概述Golang是一个跨平台的新生编程语言.今天小白就带大家一起携手走进Golang的世界.(第20课)协程存在的问题当大量的协程并发的时候,会产生资源抢占冲突... 查看详情

go并发编程之美-cas操作

参考技术A摘要:一、前言go语言类似JavaJUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有锁、CAS、原子变量操作类。相比Java来说go提供了独特的基于通道的同步措施。本节我们先来看看go中CAS操作二、... 查看详情

go语言系列之并发编程(代码片段)

Go语言中的并发编程并发与并行并发:同一时间段内执行多个任务(你在用微信和两个女朋友聊天)。并行:同一时刻执行多个任务(你和你朋友都在用微信和女朋友聊天)。Go语言的并发通过goroutine实现。goroutine类似于线程,... 查看详情

09.go语言并发(代码片段)

Go语言并发并发指在同一时间内可以执行多个任务。并发编程含义比较广泛,包含多线程编程、多进程编程及分布式程序等。本章讲解的并发含义属于多线程编程。Go语言通过编译器运行时(runtime),从语言上支持了并发的特性... 查看详情

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

Go语言学习之旅--并发编程golang并发编程之协程golang并发编程之通道golang并发编程之WaitGroup实现同步golang并发编程之runtime包golang并发编程之Mutex互斥锁实现同步golang并发编程之channel的遍历golang并发编程之selectswitchgolang并发编程之T... 查看详情

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

多字段更新?并发编程中,原子更新多个字段是常见的需求。举个例子,有一个 structPerson 的结构体,里面有两个字段。我们先更新 Person.name,再更新 Person.age ,这是两个步骤,但我们必须保证原子性。有童鞋... 查看详情

go并发编程:锁selectcontext定时器(代码片段)

...tertime.TickerSync(锁)在前面讲channel的时候,我们说到在Go语言并发编程中,倡导使用通信共享内存,不要使用共享内存通信,即goroutine之间尽量通过channel来协作。而在其他的传统语言中,都是通过共享内存加上锁机制来保证并... 查看详情

go并发编程模型(代码片段)

一、前言Go语言中实现了两种并发模型,一种是依赖于共享内存实现的线程-锁并发模型,另一种则是CSP(CommunicationingSequentialProcesses,通信顺序进程)并发模型。大多数编程语言(比如C++、Java、Python... 查看详情

6.并发编程--volatile(代码片段)

并发编程--volatilevolatile-说明volatile关键字的作用是变量在多个线程可见;volatile关键字是非原子性的要是实现原子性操作,建议使用atomic类的系列对象:支持原子性操作(注意atomic类只保证本身方法的原子性,并不保证多次操作... 查看详情

go36-29,30-原子操作(代码片段)

原子操作对于一个Go程序来说,GO语言运行时系统中的调度器会恰当的安排其中所有的goroutine的运行。不过,在同一时刻,只会有少数的goroutine真正处于运行状态。为了公平起见,调度器会频繁的切换这些goroutine。这个中断的时... 查看详情

并发编程三要素:原子性,有序性,可见性(代码片段)

并发编程三要素原子性: 一个不可再被分割的颗粒。原子性指的是一个或多个操作要么全部执行成功要么全部执行失败。有序性: 程序执行的顺序按照代码的先后顺序执行。(处理器可能会对指令进行重排序)可见性: ... 查看详情

java并发编程线程操作原子性问题(问题业务场景分析|使用synchronized解决线程原子性问题)(代码片段)

文章目录总结一、原子性问题示例二、线程操作原子性问题分析三、使用synchronized解决线程原子性问题总结原子操作问题:线程中,对变量副本count进行自增操作,不是原子操作,首先从工作内存中读取变量副本到执行引擎(操作数栈)... 查看详情