Java 动态修改配置,关于并发可见性的问题

2020-07-02 19:55:22 +08:00
 Samuelcc

最近在写一个配置中心的客户端,碰到一个问题,没有想到特别好的解决方案,和大家讨论下。

问题是这样的:

当配置发生变更时,我想自动更新 spring bean 中的 @Value 字段。 看了下有一些开源实现用的是基于反射的方式,通过设置 field 的值来实现更新

但是这样会有个问题,就是配置更新的线程修改了 field 的值,并不能保证用户其他线程可以看见最新的更改 (如果 field 上没有加 volatile,synchronized 这些保证可见性的关键字)。 但是不少开源实现好像都没有关注这个问题。

我能想到的方法:

最后的问题:

1390 次点击
所在节点    问与答
16 条回复
seaswalker
2020-07-02 20:40:57 +08:00
讲道理在 X86 平台上这种修改就是可见的,根本就不需要 volatile....
MoHen9
2020-07-02 20:41:58 +08:00
想多了,你都需要动态修改配置了,还在乎一致性问题?如果真的考虑一致性,应该使用其他方式保证,比如缓存或 zk,而不是单纯的加锁和 volatile,一般服务可能会有集群,或者多个服务使用了相同的配置,这些服务之间的一致性需要保证吗?

这种动态切换配置的做法一般在开发或部署时会用,甚至极端情况也会,这时候的一致性没有那么重要。
sagaxu
2020-07-02 20:47:39 +08:00
@seaswalker X86 上也不能保证吧
seaswalker
2020-07-02 20:56:53 +08:00
@sagaxu #3 我觉得除了写成下面这种不加 volatile 的循环导致编译器提升优化之外,x86 上应该是可见的
写过几个例子测试过这个问题: https://github.com/seaswalker/JDK/issues/8
楼主的场景编译器应该不会做这种优化,也可能我理解的有问题
Samuelcc
2020-07-02 21:02:02 +08:00
@MoHen9 我倒不是想保证强一致性,只是想有一种保证,比如说配置刷新完成,这时候我可以认为这个实例中所有线程看到的配置都是最新的。
如果不加 volatile,就无法做出保证,可能很久过去了,看到的还是旧版配置。
Samuelcc
2020-07-02 21:12:47 +08:00
@seaswalker 学到了新知识,谢谢
xiangyuecn
2020-07-02 21:15:16 +08:00
一个 56 秒的操作,你在这纠结 0.0001ms ?
sagaxu
2020-07-02 21:23:42 +08:00
@seaswalker 你用了 System.out ,那玩意儿会加锁,约束比用了 volatile 更强
Samuelcc
2020-07-02 21:27:45 +08:00
@xiangyuecn 不是时间的问题,只是想有保证,例如事务显示执行完成,这时候可以有保证不会丢失,而不是显示执行完成,但是可能在某个将来才落盘,哪怕这个将来在绝大多数情况下都很快
sagaxu
2020-07-02 21:40:41 +08:00
@seaswalker 除了加锁同步之外,你这段代码还有其他致命问题,根本不能用来验证并发问题。
javapythongo
2020-07-02 21:42:31 +08:00
spring 自带刷新,可以去了解下 @RefreshScope
momocraft
2020-07-02 21:45:33 +08:00
实验只能证明并发不安全 不能证明并发安全
Samuelcc
2020-07-02 21:47:32 +08:00
@javapythongo 这个我了解过,但是 spring 的 refresh 机制问题比较多,尤其是在 spring cloud 1.x 下,两次出线程泄漏的问题,不想用这个
ipwx
2020-07-02 21:53:32 +08:00
@seaswalker 我觉得不一定吧。那种双 CPU 架构的服务器机器。。。
seaswalker
2020-07-02 22:36:18 +08:00
@sagaxu #8 我又写了个新的例子
这次只是简单的加法,可以试一下,加上 JVM 参数-Xint,就会三秒后停止,去掉就会死循环,这不就说明了是 JIT 编译优化的锅?
况且虽然打印中有锁,但子线程对 flag 的修改没有加锁,也不满足 happens-before 吧,我的理解是打印恰恰也起到了阻止 JIT 优化的作用
sagaxu
2020-07-02 22:56:26 +08:00
@seaswalker 首先,你的理解是错的。其次,即便你的理解是对的,难道要靠禁止 jit 来保证可见性?

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

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

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

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

© 2021 V2EX