在开发过程中,我们难免要跨线程/协程进行数据的访问与修改,由此便会产生数据安全性问题,那么对于号称高并发,高性能的go语言来说,又会是怎么样的呢?我们接下来将从内置类型开始,一点一点抽丝剥茧,详细探究并发安全在go中的表现。
内置类型
基本类型
基本类型包括 int(8/16/32/64), uint(8/16/32/64), float(32/64), bool, byte, rune, complex(64/128)
基本类型的访问是安全的,但是修改操作并非安全的,我们看一个例子。
|
|
以上代码会输出什么呢?如果你回答100000
的话,那么恭喜你,你打错了,正确答案是不确定。对于不同的协程,在同一时刻有可能读到相同的count值,那么同时+1将会发生覆盖的情况,加了多次,但是最后的表现为加了一次,很遗憾,这种情况是无法精确预测的,因此对于结果来说,也是无法预测的,会产生意想不到的结果。
对于上面的加法操作来说,代码虽然只有一行,但是实际的操作会有多个步骤,首先读取count值,然后更新count值,最后替换count值。(因为int为基本类型,是拷贝而不知引用)
那么正确的做法呢?在标准库中,内置了sync/atomic
的包,顾名思义,atomic就是原子的意思,是最小的不可分割的意思,意味着,我们所有的操作都是