1

我只是想澄清一下我对 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,对吧?

谢谢。

4

3 回答 3

2

同步可能不是您所需要的。同步定义了发生前的关系,我认为这里没有必要。所以

volatile private String name; 

可能就够了。

如果发生之前真的很重要,我会选择一个公平的可重入锁


来自JLS 3 8.3.1.4 volatile 字段

Java 编程语言提供了第二种机制 [除了同步之外],易失性字段,在某些情况下它比锁定更方便。

这可能是这些目的之一。

一个字段可能被声明为 volatile,在这种情况下,Java 内存模型(第 17 节)确保所有线程都能看到变量的一致值。

无论如何,请查看 JLS 中的17.4.5 Happens-before Order并决定在这种情况下什么最适合您。

于 2013-01-23T04:26:10.847 回答
1

...可以有多个客户端通过 jconsole 调用 [ing] setName(),我需要同步 getter 和 setter 吗?

是的,如果多个线程正在调用 getter 和 setter,您可能应该这样做——就像多个本地线程正在调用 getter 和 setter 时一样。正如@user454322 所指出的,使用volatile关键字来完成内存同步也是合适的。

由于两个原因,某种形式的同步是必要的。首先,多个 JMX 操作可以同时运行,这意味着可能会发生 getter 和 setter 竞争条件。其次,即使 setter 发生在 getter 之前,也不能保证 JMX 线程在没有同步的情况下具有更新的值。这取决于每个线程获取名称的最后一个值的重要性。如果所有线程都必须看到设置的姓氏,那么您需要保持良好状态synchronized

这就是说,我们有很多关于统计信息和其他诊断信息的不同步的 JMX getter 方法,并期望 JVM 会在某个时候同步各种计数器。

于 2013-01-23T01:46:16.487 回答
1

如果您的 JMX bean 所做的只是设置字段的值,那么您需要做的就是将该字段声明为volatile. 这确保了对变量的后续读取可以看到之前的写入。

制作这些方法synchronized也提供了相同的保证,但需要额外的成本来获得监视器。

于 2013-01-23T04:15:51.877 回答