我只是想澄清一下我对JMX MBean的线程安全性的理解。
我有一个像这样简单的MBean:
public class Person
implements PersonMBean
{
private String name;
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
在可以有多个客户端访问MBean的情况下(例如,多个用户通过jconsole调用setName()),我确实需要同步getter和setter,对吗?
感谢。
答案 0 :(得分:2)
同步可能不是您所需要的。同步定义了发生之前的关系,我认为这不是必需的。 所以
volatile private String name;
可能已经足够了。
如果发生 - 在真正重要之前,我会选择fair reentrant lock。
来自 JLS 3 8.3.1.4 volatile Fields
Java编程语言提供了第二种机制[除了同步],volatile 字段,这比某些目的的锁定更方便。
这可能是其中一个目的。
字段可以声明为volatile,在这种情况下是Java内存模型 (§17)确保所有线程都看到一致的值 变量
无论如何,请查看JLS中的 17.4.5 Happens-before Order ,并确定在这种情况下最适合您的方式。
答案 1 :(得分:1)
...可以有多个客户端通过jconsole调用[ing] setName(),我是否需要同步getter和setter?
是的,如果多个线程正在调用getter和setter,你可能应该这样做 - 就像多个本地线程正在调用getter和setter一样。正如@ user454322指出的那样,使用volatile
关键字来完成内存同步也是合适的。
由于两个原因,某种形式的同步是必要的。首先,多个JMX操作可以同时运行,这意味着可以发生getter和setter竞争条件。其次,即使setter在getter之前发生,也无法保证JMX线程在没有同步的情况下具有更新的值。这取决于每个线程获取名称的最后一个值的重要性。如果所有线程都必须看到已设置的姓氏,那么您需要保持良好状态synchronized
。
这就是说,我们在统计数据和其他诊断信息上有很多不同步的JMX getter方法,并期望JVM在某些时候同步各种计数器。
答案 2 :(得分:1)
如果您的所有JMX bean都在设置字段的值,那么您需要做的就是将该字段声明为volatile
。这可以确保对变量的后续读取可以看到先前的写入。
使方法synchronized
也提供相同的保证,但需要额外的费用来获得监视器。