使用本地锁代替共享锁进行同步安全吗?
我将尝试通过以下3个案例来解释这个问题。 案例一: 我使用共享锁进行同步,使用类似这样的东西:
private static final String SHARED_LOCK = "shared_lock";
private static int i = 0;
private static int j = 0;
void increment() {
synchronized (SHARED_LOCK) {
i++;
j++;
}
}
并且它工作正常。
案例二: 现在,我在这里所做的更改是,我没有使用共享锁,而是通过执行以下操作来使用本地锁:
private static int i = 0;
private static int j = 0;
void increment() {
final String LOCAL_LOCK = "local_lock";
synchronized (LOCAL_LOCK) {
i++;
j++;
}
}
我发现代码仍然工作正常,即同步仍然有效。
案例三: 但是,当我将本地 locl 更改为:
final String LOCAL_LOCK = new String("local_lock");
然后同步就消失了。因此,在案例 II 中,本地锁能够提供同步,因为 Java 自动为我们执行了字符串文字的驻留,但在案例 III 中,因为我每次都显式创建一个新字符串,因此没有发生同步。
那么回到我原来的问题。有人觉得 CASE II 不是实现同步的正确方法吗?如果是,您能否也提及原因?
提前致谢, 萨克蒂夫。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
锁的目的是在单独线程中运行的代码之间提供同步。如果使用本地锁,每个线程将有自己的锁对象副本(在线程的堆栈中),它将在其上锁定,因此不会有同步。
它仅适用于您的情况,因为字符串实习。如果您使用
final Object LOCAL_LOCK = new Object();
它将不起作用。因此锁应该始终在线程之间共享。
Locks are meant to provide synchronization between code running in separate threads. If you use local locks, each thread will have its own copy of the lock object (in the thread's stack) on which it will lock and hence there will be no synchronization.
It works in your case only because of String interning. If you used
final Object LOCAL_LOCK = new Object();
it will not work.So locks should be always shared between threads.
仅当您在线程之间对同一对象进行同步时,同步才能正常工作;
Synchronization only works correct if you synchronize on the same object between threads;
这里非常非常重要的是,使用“规范化”对象——比如可以被保留的
String
s,或者可以共享的Integer
常量——是基本上让您可以使用与另一个类相同的锁对象。正如您所想象的那样,这是一个非常糟糕的主意。通过使用与另一个类相同的锁,您基本上可以保证自己稍后在尝试找出应用程序死锁的原因时经历痛苦的调试。
如果您需要类中的私有锁,请仅通过 new 运算符获取它,以确保它是完全唯一的对象。
(我相信 Java Puzzlers 演示文稿之一可能已经涵盖了这一点;其他一些示例参考位于 此处 和 此处)
What's very very important here is that using 'canonicalizable' objects -- like, say,
String
s, which can be interned, orInteger
constants which may be shared -- is basically opening you up to using the same lock object as another class.This is, as you'd imagine, a very bad idea. By using the same lock as another class, you can basically guarantee yourself a whole world of painful debugging later as you try and work out why your app deadlocks.
If you need a private lock in a class, make sure it is a completely unique object by obtaining it only via the
new
operator.(I believe one of the Java Puzzlers presentations might have covered this; some other example references are here and here)
这是因为字符串实习。在情况 2 中创建的所有具有相同值的字符串将“共享”同一个实例。在情况 3 中创建的字符串将是不同的实例。
正是这种差异导致了您所看到的不同同步行为。
Its because of string interning. All Strings created as in case 2 with equal values will 'share' the same instance. Strings created as in case 3 will be distinct instances.
It is this difference that accounts for the different synchronisation behaviour you're seeing.