有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

如果值是由java类的“set”方法设置的,则为反射。朗。反思。字段,它在并发中是否具有可见性?

在该方法的java文档中,没有提到并发性,因此“set”方法似乎不能确保可见性。我对此不确定

事实上,由于这个问题,我遇到了一个困难。我将构建一个基于zookeeper的分布式配置平台。与其他配置平台一样,如果某个字段由特定注释进行注释,则平台会将该字段映射到zookeeper中的节点。一旦映射节点的值更改,zookeeper watcher将通知使用此平台的项目,并使用反射(通过“设置”方法)更改注释字段

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


共 (2) 个答案

  1. # 1 楼答案

    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...类之一,等等

    如果一个线程以任何方式调用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*类就是您的答案(不确定为什么添加关键字是“乏味的”)

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

  2. # 2 楼答案

    似乎有一个基本的误解。为了确保可见性,两个端,即写入和后续读取必须正确访问变量。不可能有一个神奇的setter可以“确保”非volatile变量的可见性。声明变量volatile将强制读者和作者确保可见性

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