Java的`synchronized`块是锁定对象引用还是值?

4
给出下面的输出结果:
    Path path1 = Paths.get("/Users/someone/foo");
    Path path2 = Paths.get("/Users/someone/foo");
    System.out.println(path1.toString() == path2.toString()); // outputs false
    System.out.println(path1.toString().equals(path2.toString())); // outputs true

以下是两个线程,是否可能同时运行于关键部分?

    // Thread 1
    synchronized (path1.toString()) {
        // Critical section
    }

    // Thread 2
    synchronized (path2.toString()) {
        // Critical section
    }

1
每个对象都有自己的监视器;这是由同步块获取的。因此,只有在 path1.toString() == path2.toString() 的情况下才会有互斥。 - Andy Turner
1
一般来说,同步方法调用的结果并不是一个好主意:即使你在两个线程中只同步path1.toString(),如果它总是返回一个新对象(你不知道是否是这种情况,而且它可能会任意更改),你可能根本没有互斥。 - Andy Turner
你肯定不能指望那些引用是相同的。很可能它们不会是相同的。无论如何,为什么要锁定一个 StringString携带了大量的负载和语义,仅仅作为锁对象使用。你只需要一个 Object - Lew Bloch
2个回答

7
参考值即为值本身。这只是一种没有区别的区分。toString()是一个引用。除非两个值都被存储,或者它们来自相同的字符串字面量,否则它不会与任何其他toString()值相同。请保留HTML标记。

1
我认为 OP 想知道使用 equals() 测试相等的两个字符串是否足以确保线程安全。 - Ted Hopp
@TedHopp 我不认为猜测他可能意味着什么有任何意义。我正在回答他所问的问题。 - user207421
是的Ted,我在想在synchronized()关键字中判断两个对象是否相等时,是使用equals()还是== - albusshin
1
@albusshin 那么你应该在问题中说明。一旦你把它写下来,你就会发现它没有意义。为什么synchronized会比较对象? - user207421
@EJP 我明白你的意思。请原谅我的行话,但我不知道我们在调用 .equals() 时比较的东西叫什么名字? - albusshin
1
@albusshin,这不是一个“东西”,而是一个方法。它可以比较任何它喜欢的东西或什么都不比较,并返回一个值。 - user207421

4
正如Java语言规范第14.19节所述,synchronized语句锁定对象。如果您认为"value"是字符串值(例如 path1.toString().equals(path2.toString())),则答案是否定的——您的代码几乎肯定不是线程安全的。根据JLS的说法,如果表达式的类型是引用类型(synchronized语句要求),那么该表达式的null或一个对象。除非两个toString()调用返回相同的对象引用(path1.toString() == path2.toString()),否则您发布的代码中的两个块并不是互斥的。

这与所引用的参考资料相反。它说:“否则,让表达式的非空值为V。执行线程锁定与V相关联的监视器。” 它锁定与表达式相关联的监视器,而不是此答案所声称的引用。此外,正如§17.1所述,监视器与对象相关联,而不是引用。 “Java中的每个对象都与监视器相关联,线程可以锁定或解锁该监视器。” - Lew Bloch
@LewBloch 再次强调,这是毫无区别的区分。它是一个引用值表达式。 - user207421
说出JLS相反的话确实有所不同,特别是当它回答了提问者所问的确切问题并给出了相反的答案时。不仅如此,在像这样的论坛上只需要阅读几分钟,就会看到对象和引用(指针)之间的混淆会造成多大的损害。这在锁定、GC、多态性、复制和克隆、不可变性、参数传递(以及是否按值传递)等方面都很重要 - 真的是所有事情。因此,你声称这是“毫无差别”的说法与它试图维护的答案一样不真实。 - Lew Bloch
1
@LewBloch - 有道理。我稍微修改了措辞,以明确Java锁定对象而不是引用。 - Ted Hopp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接