基于声明为 "final static Object" 的对象的同步与简单的 "final Object"

Synchronization based on an object declared as "final static Object" vs. simply "final Object"

我有一个关于 Java 并发的问题。如果我同步一个基于对象的关键部分,将该变量声明为 final static Object 与简单地 final Object.

之间有什么区别

我明白 static 关键字定义一个属于 class 的变量,但我对它在多线程环境中的含义有点模糊。

请参考下面的代码示例。目前我将 lock 对象声明为 private final Object lock = new Object(),如果我添加 static 关键字会有什么不同?

class ConcurrencySample {
    private String message = null;
    private final Object lock = new Object();
    //private final static Object lock = new Object();

    public void setMessage(String msg) {
        synchronized (lock) {
            message = msg;
        }
    }
    public String getMessage() {
        synchronized (lock) {
            String temp = message;
            message = null;
            return temp;
        }
    } 
}

感谢您的帮助!

使 lock 变量 static 将使任何针对 ConcurrencySampleany 实例读取或写入消息的线程阻塞,因为反对仅在另一个线程正在读取的特定实例上阻塞。

它基本上会降低应用程序的并发级别:只有一个线程可以在任何实例上读取或写入消息,即使其他线程想要影响完全不同的实例也是如此。

如果您将对象声明为 static final,则 class 的所有实例共享一个锁。这意味着如果两个独立的实例各自尝试在其上同步,则两个实例中只有一个能够同时获得锁。

如果您将对象声明为 final,那么 class 的每个实例都有一个锁副本,因此如果 class 的两个独立实例各自尝试获得锁,他们每个人都获得自己的锁,所以不涉及阻塞。但是,如果多个线程都同时调用 class 的一个实例上的方法,这些线程将尝试获取同一个对象,因此一次只能有一个线程继续进行。

希望对您有所帮助!