如果一个值是由 Class java.lang.reflect.Field 的 'set' 方法设置的,它是否具有并发可见性?

if a value is set by 'set' method of Class java.lang.reflect.Field, does it have visibility in concurrency?

这个方法的java文档中并没有提到并发,所以'set'方法似乎没有保证可见性。我不确定。

其实我因为这个问题遇到了一个难点。我打算搭建一个基于zookeeper的分布式配置平台。和其他配置平台一样,如果一个字段被特定注解注解,平台会把这个字段映射到zookeeper中的一个节点。一旦映射节点的值发生变化,使用该平台的项目将通过zookeeper watcher通知并使用反射更改注释字段(通过'set'方法)。

使用我的配置平台的项目很可能是一个web应用,它在服务层只有一个对象,所以该字段总是并发访问。如果 'set' 方法不能确保可见性,我是否必须强制项目为注释字段添加关键字 volatile?我看起来很奇怪而且乏味。有没有更好的方法来解决这个问题?其他配置平台如何解决这个问题?

似乎存在根本性的误解。为了保证可见性,both结束,即写之后的读,必须适当地访问变量。不可能有魔法 setter 可以“确保”非 volatile 变量的可见性。声明变量 volatile 将强制读者和作者确保可见性。

也不清楚为什么将变量声明为 volatile 以获得 volatile 语义对您来说看起来“奇怪而乏味”。您不必这样声明它,因为通过反射进行更改,但因为存在通常需要线程间可见性的更改。

In java doc of this method, concurrency is not mentioned, so it seems that the 'set' method do not ensure visibility. I'm not sure about this.

通过反射调用set方法与并发无关,它是关于可访问性的。并发是关于字段如何被具体标记的。它是 volatile 字段,Atomic... class 字段之一,等等?

如果一个线程以任何方式调用 set 方法(setFoo() 方法,通过反射或其他代码),那么其他线程可能看不到这个更新的值,直到执行写入的线程通过写入内存屏障以确保发布到主内存,其他线程跨越读取屏障以确保更新它们的每个处理器内存缓存。

If the 'set' method do not ensure visibility, do I must force the project add Keyword volatile for the annotated field ?

是的,你知道。对于要在线程之间共享的 任何 字段,您需要弄清楚该字段是如何同步的。

I looks strange and tedious. Is there some better way about this problem ? How do the other configuration platforms solving this ?

这个问题的答案在一定程度上取决于您的要求。如果您需要在每次访问时将此字段更新为最新值,则将其标记为 volatile 或切换为 Atomic* class 是您的答案(不确定为什么添加关键字是 "tedious").

您可以使用的另一种机制是让每个请求在请求开始时以同步方式更新某种配置对象,然后在处理请求时使用它的缓存配置对象。