静态块中的thread.join()引起的死锁

发布于 2024-11-19 19:42:57 字数 1040 浏览 0 评论 0原文

我遇到了一个死锁场景,可以概括为如下所示的 StaticDeadlock 类。

这个简单的程序将冻结在o.getClass()处。这是我对发生的事情的猜测,但有人可以更好地解释它吗?

1) 程序进入 StaticDeadlock 静态块

2) 线程启动

3) 主线程处于等待线程完成的状态,因此不能完成静态块

4) 在线程内它访问StaticDeadlock.o,但StaticDeadlock的静态块尚未完成。因此程序冻结了?

    public class StaticDeadlock
    {
        private static final Object o = new Object();

        static {
            MyThread thread = new MyThread();
            thread.start();

            try {
                thread.join();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public static void main (String[] args)
        {
            System.out.println("all is well.");
        }

        static class MyThread extends Thread
        {
            @Override
            public void run ()
            {
                System.out.println("inside mythread");
                o.getClass();
            }
        }

    }

I came across a deadlock scenario which can be summarized as the StaticDeadlock class shown below.

This simple program will freeze at o.getClass(). Here's my speculation of what happened, but can someone explain it better?

1) the program enters StaticDeadlock static block

2) thread starts

3) main thread is put in wait for thread to finish, hence can't finish the static block

4) inside thread it access StaticDeadlock.o but StaticDeadlock's static block is not finished yet. Hence the program freezes?

    public class StaticDeadlock
    {
        private static final Object o = new Object();

        static {
            MyThread thread = new MyThread();
            thread.start();

            try {
                thread.join();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public static void main (String[] args)
        {
            System.out.println("all is well.");
        }

        static class MyThread extends Thread
        {
            @Override
            public void run ()
            {
                System.out.println("inside mythread");
                o.getClass();
            }
        }

    }

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

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

发布评论

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

评论(1

没有心的人 2024-11-26 19:42:57

是的,差不多就是这样。新线程在访问静态成员之前等待 StaticDeadlock 的类初始值设定项完成。请参阅Java 语言规范的第 12.4.2 节< /a> 了解更多详细信息,特别是以下步骤:

  1. 在表示要初始化的类或接口的 Class 对象上进行同步(第 14.19 节)。这涉及到等待,直到当前线程可以获得该对象的锁(第 17.1 节)。

  2. 如果其他线程正在对类或接口进行初始化,则等待此 Class 对象(这会暂时释放锁)。当当前线程从等待中唤醒时,重复此步骤。

  3. 如果当前线程正在对类或接口进行初始化,则这一定是初始化的递归请求。释放Class对象上的锁并正常完成。

  4. 如果类或接口已初始化,则无需执行进一步操作。释放Class对象上的锁并正常完成。

它甚至不会在第二个线程中通过第 1 步,因为第一个线程拥有锁并且不会释放它。

请注意,它不会调用导致问题的 getClass() - 执行任何需要 o 值的操作都会使第二个线程等待,直到类初始值设定项已完成,这当然不会发生,因为第一个线程正在等待第二个线程完成。

Yes, that's pretty much it. The new thread is waiting for the class initializer of StaticDeadlock to complete before it accesses the static member. See section 12.4.2 of the Java Language Specification for more details, in particular these steps:

  1. Synchronize (§14.19) on the Class object that represents the class or interface to be initialized. This involves waiting until the current thread can obtain the lock for that object (§17.1).

  2. If initialization is in progress for the class or interface by some other thread, then wait on this Class object (which temporarily releases the lock). When the current thread awakens from the wait, repeat this step.

  3. If initialization is in progress for the class or interface by the current thread, then this must be a recursive request for initialization. Release the lock on the Class object and complete normally.

  4. If the class or interface has already been initialized, then no further action is required. Release the lock on the Class object and complete normally.

It won't even get past step 1 in the second thread, as the first thread has the lock and won't release it.

Note that it's not calling getClass() which causes the problem - doing anything which requires the value of o will make the second thread wait until the class initializer has completed, which of course won't happen because the first thread is waiting for the second thread to finish.

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