go语言sync.atomic源码阅读

柯里珊瑚
• 阅读 783

一、atomic包与原子操作

atomic包是Go语言提供的原子操作(atomic operation)原语的相关接口。原子操作是相对于普通指令操作而言的。以一个整型变量自增的语句为例:

var i int
i++

i++这行语句需要以下3条普通机器指令来完成变量i的自增。

LOAD:将变量从内存加载到CPU寄存器。
ADD:执行加法指令。
STORE:将结果存储回原内存地址。

这3条普通指令在执行过程中是可中断的。而原子操作的指令是不可中断的,它就好比一个事务,要么不执行,一旦执行就一次性全部执行完毕,不可分割。
正因如此,原子操作可用于共享数据的并发同步。

二、i++ 100次在并发与非并发为什么得到了不同的值

func TestI100(t *testing.T) {
    sum := 0
    for i := 0; i < 100; i++ {
        sum += i
    }
    t.Log(sum) //sum = 4950
}
func TestGoroutineI100(t *testing.T) {
    sum := 0
    for i := 0; i < 100; i++ {
        go func(j int) {
            sum += j
        }(i)
    }
    t.Log(sum) //sum = 2421
}
func TestAtomicI100(t *testing.T) {
    var sum int32
    for i := 0; i < 100; i++ {
        go func(j int) {
            atomic.AddInt32(&sum, int32(j))
        }(i)
    }
    t.Log(sum) //4278
}

sum的正确值是 4950,TestGoroutineI100() 为啥错误?

并发的情况下,不同的协程goroutine同时拿到一个 sum值,然后执行 += 此时就会出现上面的问题。

谢谢您的观看,欢迎关注我的公众号。

go语言sync.atomic源码阅读

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Wesley13 Wesley13
3年前
C++原子类实现
引言在系统实现的过程中,经常需要用到计数功能,为了多线程下的安全使用,我自己定义了一个原子类。基于Mutex的实现我基于Mutex实现了一个简单的原子类,代码如下/说明:自定义整数操作的原子类,减少代码中的各种锁/ifndef_ATOMIC_INT64
Wesley13 Wesley13
3年前
PIC中档单片机汇编指令详解(5)
位操作指令详述BCF数据寄存器指定位清0语法形式:BCFf,b操作数:f为数据寄存器的低7位地址(0x00~0x7F)B为数据位编号(0~7)执行时间:一个指令周期执行过程:使数据寄存器f的的b位清0状态标志影响:无说明:该指令可对任何数据寄存器的任意一个位置清0,常用于标志位的设定和清除,或者把某一管脚置成低电平。指
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
MySQL数据库InnoDB存储引擎Log漫游(1)
作者:宋利兵来源:MySQL代码研究(mysqlcode)0、导读本文介绍了InnoDB引擎如何利用UndoLog和RedoLog来保证事务的原子性、持久性原理,以及InnoDB引擎实现UndoLog和RedoLog的基本思路。00–UndoLogUndoLog是为了实现事务的原子性,
Wesley13 Wesley13
3年前
NEO从源码分析看UTXO交易
_0x00前言_社区大佬:“交易是操作区块链的唯一方式。”_0x01交易类型_在NEO中,几乎除了共识之外的所有的对区块链的操作都是一种“交易”,甚至在“交易”面前,合约都只是一个小弟。交易类型的定义在Core中的TransactionType中:源码位置:neo/Core/TransactionType
Wesley13 Wesley13
3年前
Java5的 线程并发库
java.util.concurrent.atomic一个小型工具包,支持单个变量上的无锁线程安全编程.包含的类:!(https://oscimg.oschina.net/oscnet/8f3ab6f1c9d0301b0422db204ec0abd4187.png)这些类的相关操作都是
Wesley13 Wesley13
3年前
JDK中的Atomic包中的类及使用
引言Java从JDK1.5开始提供了java.util.concurrent.atomic包,方便程序员在多线程环境下,无锁的进行原子操作。原子变量的底层使用了处理器提供的原子指令,但是不同的CPU架构可能提供的原子指令不一样,也有可能需要某种形式的内部锁,所以该方法不能绝对保证线程不被阻塞。Atomic包介绍在JDK1
Wesley13 Wesley13
3年前
JDK1.5 AtomicLong实例
JDK1.5AtomicLong实例类AtomicLong可以用原子方式更新的long值。有关原子变量属性的描述,请参阅java.util.concurrent.atomic包规范。AtomicLong可用在应用程序中(如以原子方式增加的序列号),并且不能用于替换Long。但是,此类确实扩展了Number,允