Go 读取全局变量要加锁?!

2019-03-13 16:48:33 +08:00
 index90

在看同事的代码时候,发现这样的操作:

var (
  object = New()
  mu = sync.RWMutex
)

func SetValue(v SomeInterface) {
  mu.Lock()
  object = v
  mu.Unlock()
}

func GetValue() SomeInterface {
  mu.RLock()
  defer mu.RUnlock()
  return object
}  

为什么要加读锁啊?!难道会 Get 到 nil ? 同事给了我这个链接: https://stackoverflow.com/questions/21447463/is-assigning-a-pointer-atomic-in-golang

10797 次点击
所在节点    Go 编程语言
51 条回复
richzhu
2019-03-14 10:35:41 +08:00
@wweir 看了您的文章,非常感谢~ 干货满满
cloudzhou
2019-03-14 10:37:40 +08:00
@index90 取决于这个对象调用的方法,访问的变量,是否存在竞争冲突

@zarte 并发里面存在两个问题:
1. 内存可见性,从寄存器 -》 L1,L2 cache -》主内存,变量的赋值,对于其他线程,可见性是不可保证的,读取的可能是旧数据
2. 赋值本身的原子性,举个例子,消息是 32 位单位,但是需要赋值一个 int64,那么是两条 cpu 消息,分别赋值前后 32 bit 的数据,那么 a = b,a 存在一个阶段,是一种中间状态,不是之前的 a1,也不是新的值 a2

并发编程,比你想象的更难
reus
2019-03-14 10:39:48 +08:00
@zarte 你只需要记得一条规则:并发读写要上锁,不管读写的是什么。这样你就能避免所有的竞态问题,包括未来可能出现的。另外,很多人口里说“读到旧数据没问题”,实际绝大部分都不知道乱序执行,以为读到某个值了,就等于前面的某些指令就已经执行了,做了一些错误的假定。
index90
2019-03-14 10:42:24 +08:00
@zarte 我也觉得不可能啊,但事实就是这样,官方文档都说了。
我在想,为了线程安全,以后我实现的 struct,成员变量都不应该暴露了,成员变量的变更,都应该加锁。
简直颠覆认知,越来越觉得自己不配当程序员了。
index90
2019-03-14 10:48:14 +08:00
@cloudzhou 不是很明白,我在考虑的是,如果每个线程都独享一个对象,那么我们是不是就“尽量避免并发”,但是这样做会以性能损失作为代价。如果多个线程共享一个对象,那么我们在实现的时候,就要考虑线程安全的问题,代价就是程序的复杂度。
我的问题是,如何作出平衡的?
tt67wq
2019-03-14 10:49:59 +08:00
楼主学过操作系统???
index90
2019-03-14 10:52:58 +08:00
@tt67wq 我还实现过 pintos 呢,学得不好,一知半解,问的问题太低级了,让各位大神见笑。
cloudzhou
2019-03-14 10:53:13 +08:00
@index90 这个看你需求,以及对象本身是否“比较重”,初始化的代价等。
举个例子,spring been singleton vs prototype,就是对象是返回一个单例还是完全一个新对象
单例需要考虑并发问题,新对象不需要
zarte
2019-03-14 11:13:50 +08:00
@cloudzhou 谢谢,第二点这个不知道。
sdrzlyz
2019-03-14 11:22:38 +08:00
没毛病。。。如果 Set 跟 Get 完全没有并发操作,无所谓(那这种情下,大写一个变量不就完了。。。)
ihciah
2019-03-14 11:43:08 +08:00
感觉有脏读问题,但至于说赋值是不是原子性的,我觉得应该是。如果你不是分拆赋值(x.a=1 x.b=2),单个地址(占用一个寄存器)的赋值操作在机器码上应该是单个指令。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/544205

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX