使用本地锁代替共享锁进行同步安全吗?

发布于 2024-09-14 00:55:21 字数 981 浏览 6 评论 0 原文

我将尝试通过以下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 不是实现同步的正确方法吗?如果是,您能否也提及原因?

提前致谢, 萨克蒂夫。

I will try to explain the quetion by taking following 3 cases.
CASE I:
I was using shared lock for synchronization using something like this:


         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++;
        }
    }

And it is working fine.

CASE II:
Now What I have changed here is instead of using shared lock I thought of using a local lock by doing something like this:


         private static int i = 0;
         private static int j = 0;
    void increment() {
        final String LOCAL_LOCK = "local_lock";
                  synchronized (LOCAL_LOCK) {
            i++;
            j++;
        }
    }

And I found that code was still working fine that is synchronization was still working.

CASE III:
However when I changed the local locl to this:

final String LOCAL_LOCK = new String("local_lock");

then the synchronization went away. So it looks like that in CASE II the local lock was able to provide synchronization because of interning of String literals that Java does for us automatically but in CASE III as I was explicitly creating a new String everytime thus synchronization was not happening.

So coming back to my original question. Does anyone feels that CASE II is not the right way to achieve synchronization? If yes could you please also mention why?

Thanks in advance,
SacTiw.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

春风十里 2024-09-21 00:55:21

锁的目的是在单独线程中运行的代码之间提供同步。如果使用本地锁,每个线程将有自己的锁对象副本(在线程的堆栈中),它将在其上锁定,因此不会有同步。

它仅适用于您的情况,因为字符串实习。如果您使用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.

只是偏爱你 2024-09-21 00:55:21

仅当您在线程之间对同一对象进行同步时,同步才能正常工作;

  • 第一种情况是显而易见的,
  • 在第二种情况下,Java 编译器会实习字符串常量,这就是它也能工作的原因(您在调用之间从字符串池中获取相同的对象),
  • 第三种情况您强制创建一个新的字符串对象,因此您是每个线程获得自己的私有锁,根本不进行同步。

Synchronization only works correct if you synchronize on the same object between threads;

  • The 1st case is obvious,
  • In the second case the Java compiler interns the string constant which is why it works too (you get the same object from the string pool between calls),
  • The 3rd case you force a new string object and therefore you are getting your own private lock per thread giving no synchronization at all.
孤芳又自赏 2024-09-21 00:55:21

这里非常非常重要的是,使用“规范化”对象——比如可以被保留的Strings,或者可以共享的Integer常量——是基本上让您可以使用与另一个类相同的锁对象。

正如您所想象的那样,这是一个非常糟糕的主意。通过使用与另一个类相同的锁,您基本上可以保证自己稍后在尝试找出应用程序死锁的原因时经历痛苦的​​调试。

如果您需要类中的私有锁,请仅通过 new 运算符获取它,以确保它是完全唯一的对象。

(我相信 Java Puzzlers 演示文稿之一可能已经涵盖了这一点;其他一些示例参考位于 此处此处

What's very very important here is that using 'canonicalizable' objects -- like, say, Strings, which can be interned, or Integer 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)

峩卟喜欢 2024-09-21 00:55:21

这是因为字符串实习。在情况 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文