如果值是由java类的“set”方法设置的,则为反射。朗。反思。字段,它在并发中是否具有可见性?
在该方法的java文档中,没有提到并发性,因此“set”方法似乎不能确保可见性。我对此不确定
事实上,由于这个问题,我遇到了一个困难。我将构建一个基于zookeeper的分布式配置平台。与其他配置平台一样,如果某个字段由特定注释进行注释,则平台会将该字段映射到zookeeper中的节点。一旦映射节点的值更改,zookeeper watcher将通知使用此平台的项目,并使用反射(通过“设置”方法)更改注释字段
使用我的配置平台的项目可能是一个web应用程序,它在服务层中只有一个对象,因此该字段总是以并发方式访问。如果“set”方法不能确保可见性,我是否必须强制项目为注释字段添加关键字volatile?我看起来既奇怪又乏味。有没有更好的办法解决这个问题?其他配置平台如何解决这个问题
# 1 楼答案
通过反射调用
set
方法与并发无关,而是关于可访问性。并发性是关于字段的具体标记方式。它是volatile
字段还是Atomic...
类之一,等等如果一个线程以任何方式调用
set
方法(setFoo()
方法,通过反射或其他代码),那么其他线程可能看不到这个更新的值,直到执行写入操作的线程跨越写入内存屏障以确保发布到主内存,而其他线程跨越读取屏障以确保其每处理器内存缓存更新了是的,你知道。对于希望在线程之间共享的任何字段,您需要弄清楚该字段是如何同步的
这个问题的答案在一定程度上取决于你的要求。如果您需要在每次访问时将此字段更新为最新值,那么将其标记为
volatile
或切换到Atomic*
类就是您的答案(不确定为什么添加关键字是“乏味的”)您可以使用的另一种机制是,让每个请求在请求开始时以同步方式更新某种配置对象,然后在处理请求时使用其缓存的配置对象
# 2 楼答案
似乎有一个基本的误解。为了确保可见性,两个端,即写入和后续读取必须正确访问变量。不可能有一个神奇的setter可以“确保”非
volatile
变量的可见性。声明变量volatile
将强制读者和作者确保可见性同样不清楚的是,为什么将变量声明为
volatile
以获得volatile
语义在您看来“既奇怪又乏味”。您不必这样声明它,因为通过反射进行的更改,而是因为存在需要线程间可见性的更改