为什么在 Integer 上同步时,notifyAll() 会引发 IllegalMonitorStateException?

发布于 2024-07-09 07:39:02 字数 529 浏览 13 评论 0原文

为什么这个测试程序会导致java.lang.IllegalMonitorStateException

public class test {
    static Integer foo = new Integer(1);
    public static void main(String[] args) {
        synchronized(foo) {
            foo++;
            foo.notifyAll();
        }
        System.err.println("Success");
    }
}

结果:

Exception in thread "main" java.lang.IllegalMonitorStateException
        at java.lang.Object.notifyAll(Native Method)
        at test.main(test.java:6)

Why does this test program result in a java.lang.IllegalMonitorStateException?

public class test {
    static Integer foo = new Integer(1);
    public static void main(String[] args) {
        synchronized(foo) {
            foo++;
            foo.notifyAll();
        }
        System.err.println("Success");
    }
}

Result:

Exception in thread "main" java.lang.IllegalMonitorStateException
        at java.lang.Object.notifyAll(Native Method)
        at test.main(test.java:6)

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

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

发布评论

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

评论(4

温柔戏命师 2024-07-16 07:39:02

您已经正确地注意到,notifyAll 必须从同步块调用。

但是,在您的情况下,由于自动装箱,您同步的对象不是您调用 notifyAll 的同一实例。 事实上,新的、递增的 foo 实例仍然限制在堆栈中,并且任何其他线程都不可能在 wait 调用上被阻塞。

您可以实现自己的可变计数器,并在其上执行同步。 根据您的应用程序,您可能还会发现 AtomicInteger 满足您的需求。

You have noted correctly that notifyAll must be called from a synchronized block.

However, in your case, because of auto-boxing, the object you synchronized on is not the same instance that you invoked notifyAll on. In fact, the new, incremented foo instance is still confined to the stack, and no other threads could possibly be blocked on a wait call.

You could implement your own, mutable counter on which synchronization is performed. Depending on your application, you might also find that AtomicInteger meets your needs.

凶凌 2024-07-16 07:39:02

您还应该对锁定或通知诸如 String 和 Integer 等可以被 JVM 保留的对象保持警惕(以防止创建大量表示整数 1 或字符串“”的对象)。

You should also be leery of locking or notifying on objects like String and Integer that can be interned by the JVM (to prevent creating a lot of objects that represent the integer 1 or the string "").

佞臣 2024-07-16 07:39:02

增加 Integer 会使旧的 foo 消失并被一个全新的对象 foo 取代,该对象与之前的 foo 变量不同步。

这是埃里克森上面建议的 AtomicInteger 的实现。 在此示例中 foo.notifyAll(); 不会产生 java.lang.IllegalMonitorStateException 因为 AtomicInteger 对象在 foo.incrementAndGet(); 时没有刷新; 正在运行。

import java.util.concurrent.atomic.AtomicInteger;

public class SynchronizeOnAPrimitive {
    static AtomicInteger foo = new AtomicInteger(1);
    public static void main(String[] args) {
        synchronized (foo) {
            foo.incrementAndGet();
            foo.notifyAll();
        }
        System.out.println("foo is: " + foo);
    }
}

输出:

foo is: 2

Incrementing the Integer makes the old foo disappear and be replaced with a brand new object foo which is not synchronized with the previous foo variable.

Here is an implementation of AtomicInteger that erickson suggested above. In this example foo.notifyAll(); does not produce a java.lang.IllegalMonitorStateException beause the AtomicInteger Object is not refreshed when foo.incrementAndGet(); is run.

import java.util.concurrent.atomic.AtomicInteger;

public class SynchronizeOnAPrimitive {
    static AtomicInteger foo = new AtomicInteger(1);
    public static void main(String[] args) {
        synchronized (foo) {
            foo.incrementAndGet();
            foo.notifyAll();
        }
        System.out.println("foo is: " + foo);
    }
}

Output:

foo is: 2
記柔刀 2024-07-16 07:39:02

正如埃里克森所指出的,没有后增量运算符的代码可以正常工作,不会出现错误:

static Integer foo = new Integer(1);

public static void main(String[] args) {
    synchronized (foo) {
        foo.notifyAll();
    }
    System.out.println("Success");
}

输出:

成功

As erickson has noted, the code without the postincrement operator works without error:

static Integer foo = new Integer(1);

public static void main(String[] args) {
    synchronized (foo) {
        foo.notifyAll();
    }
    System.out.println("Success");
}

output:

Success

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