Java 锁 : How equality check for Monitor locks is done in synchronized block?

标签 java concurrency locking synchronized

当你在一个对象上有几个synchronized block 时(比如说)obj那么Java如何检查所有这些obj是否是相同还是不同?

例如:

public static f() {
    synchronized ("xyz") {
        ...
    }
}

如果上面的函数 f 被两个线程同时调用,它们会阻塞另一个吗?请注意,每个线程都会获得一个新的 String 对象实例。

为了检查这一点,我编写了以下测试代码,看起来上面的 block 确实可以工作,但是还有其他意想不到的结果。

public class Test {

    public static void main(String[] args){

        new Thread() {
            public void run() {
                //f1("A", new X());
                f1("A", "Str");
            }
        }.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //f1("B", new X());
        f1("B", "Str");
    }

    public static void f1(String a, Object x) {
        synchronized(x) {
            System.out.println("f1: " + a);
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f1: " + a + " DONE");
        }
    }

    private static class X {
        public boolean equals(Object o) {
            System.out.println("equals called");
            return true;
        }

        public int hashCode() {
            System.out.println("hashCode called");
            return 0;
        }
    }

}

如果您运行上面的代码,您将得到以下输出:-

f1: A
f1: A DONE
f1: B
f1: B DONE

但是,如果我注释 f1("A", "Str");f1("B", "Str"); 行并取消注释在它们上面的线,那么结果是:-

f1: A
f1: B
f1: A DONE
f1: B DONE

由于 Str 版本有效,所以我期待 Java 可能使用 equals 检查 synchronized block 或者 hashCode 但从第二次测试看来,情况完全不是这样。

String 是特例吗?

最佳答案

不,Java 不使用 equals 作为锁监视器。

锁在对象实例本身上。所以,在某种程度上,它使用了“==”,如果你愿意的话(但实际上,这不是它的实现方式。每个对象都有一个用于当前锁所有者的特殊插槽)。

String 没有特殊情况。

但是,字符串发生的事情是,字符串字面量被合并,如果您多次使用相同的字面量,它将产生相同的实例(而 new X 创建不同的实例, new String)。如果您对"new"字符串调用 intern,您可能会看到相同的效果。

关于Java 锁 : How equality check for Monitor locks is done in synchronized block?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12139849/

相关文章:

java - Guava 并发教程/代码

Java 读写锁节省内存资源

java - 重新获取锁

java - 无法在 Ubuntu 上使用 JDK 9 启动 Eclipse Neon - 退出代码 = 13

java - java中字符串分割的问题(Android)

java - 支持动态数据库的最佳方法

java - 如何让 java.concurrency.CyclicBarrier 按预期工作

java - 上下文 getRealPath() 用于不存在的文件

sql - 简单的 UPDATE 和 DELETE 语句可以触发 PostgreSQL 中的死锁和回滚吗?

c# - 另一个锁定问题