Java锁:如何在synchronized块中完成Monitor锁的相等检查?

时间:2012-08-27 10:00:22

标签: java concurrency locking synchronized

如果对象(比如说)synchronized上有几个obj块,那么Java如何检查所有这些obj是否相同或不同?

例如:

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

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

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

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块或hashCode但是从第二次测试看来,它不是这个案子。

String是特例吗?

1 个答案:

答案 0 :(得分:21)

不,Java不会将equals用于锁定监视器。

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

String没有特殊情况。

Strings正在发生的事情是,字符串文字被合并,如果你有多次相同的文字,它将产生相同的实例(而new X创建不同的实例,就像{{ {1}})。如果你在“新”字符串上调用new String,你可能会看到相同的效果。

相关问题