在这个方法的java doc中,没有提到并发性,所以似乎' set'方法不保证可见性。我对此不太确定。
事实上,由于这个问题,我遇到了一个困难。我将基于zookeeper构建一个分发配置平台。与其他配置平台一样,如果某个字段由特定注释注释,则该平台会将此字段映射到zookeeper中的节点。一旦映射节点的值发生变化,使用此平台的项目将由zookeeper观察者通知,并使用反射更改带注释的字段(通过' set'方法)。
使用我的配置平台的项目可能是一个Web应用程序,它在服务层中只有一个对象,因此该字段始终以并发方式访问。如果'设置'方法无法确保可见性,是否必须强制项目为注释字段添加关键字 volatile ?我看起来很奇怪,乏味。这个问题有更好的方法吗?其他配置平台如何解决这个问题?
答案 0 :(得分:2)
似乎存在一种根本的误解。为了确保可见性,两个结束,即写和后续读取,必须适当地访问变量。对于非volatile
变量,不能有“确保可见性”的魔术设置器。声明变量volatile
将迫使读者和作者同时确保可见性。
还不清楚为什么将变量声明为volatile
以获得volatile
语义看起来“奇怪而乏味”。您不必声明它,因为通过Reflection进行更改,但是由于存在需要线程间可见性的更改。
答案 1 :(得分:2)
在这个方法的java doc中,没有提到并发性,所以似乎' set'方法不保证可见性。我对此不太确定。
通过反射调用set
方法与并发性无关,而是与可访问性无关。并发性是关于字段如何被特别标记的。它是volatile
字段,Atomic...
类之一,等等吗?
如果一个线程以任何方式调用set
方法(setFoo()
方法,通过反射或其他代码),那么其他线程可能看不到此更新的值,直到执行写入的线程跨写内存屏障,以确保发布到主内存和其他线程跨越读屏障,以确保更新其每处理器内存缓存。
如果'设置'方法不保证可见性,是否必须强制项目为注释字段添加关键字volatile?
是的,你这样做。对于要在线程之间共享的任何字段,您需要确定字段的同步方式。
我看起来很奇怪而乏味。这个问题有更好的方法吗?其他配置平台如何解决这个问题?
答案取决于您的要求。如果您需要将此字段更新为每次访问时的最新值,则将其标记为volatile
或切换为Atomic*
类是您的答案(不确定为什么添加关键字是"乏味&#34 ;)
您可以使用的另一种机制是让每个请求以同步方式在请求开始时更新某种配置对象,然后在处理请求时使用它的缓存配置对象。