同时执行Thread.interrupt() Object.notify(),为什么会有两个结果?

public class WaitNotifyAll {

    private static volatile Object resourceA = new Object();


    public static void main(String[] args) throws Exception {

        Thread threadA = new Thread(new Runnable() {

            @Override

            public void run() {

                synchronized (resourceA) {

                    try {

                        System.out.println("threadA begin wait");

                        resourceA.wait();

                        System.out.println("threadA end wait");

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }

                }

            }

        });


        Thread threaB = new Thread(new Runnable() {

            @Override

            public void run() {

                synchronized (resourceA) {

                    System.out.println("threadC begin notify");

                    threadA.interrupt();

                    resourceA.notify();

                }

            }

        });


        threadA.start();


        Thread.sleep(1000);


        threaB.start();


        System.out.println("main over");

    }

 }

这里有两种可能的结果:

  1. 抛出中断异常

  2. 正常终止

为什么?

我不明白。当threadA被中断时,结果应该抛出InterruptedException。但有时执行这个程序,它可以正常完成。

环境:java8,mac


UYOU
浏览 160回答 2
2回答

PIPIONE

当线程同时接收到中断和通知时,行为可能会有所不同。请参考https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.2.3信用 - 并发兴趣邮件列表上的 Alex Otenko

森栏

因为重新排序。在正常终止编译器重新排序指令中断和通知中,中断在工作线程上调用并且没有中断异常抛出。尝试通过读取 volatile 变量来禁止重新排序,您总是会遇到异常中断。public class WaitNotifyAll {private static volatile Object resourceA = new Object();public static void main(String[] args) throws Exception {    Thread threadA = new Thread(new Runnable() {        @Override        public void run() {            synchronized (resourceA) {                try {                    System.out.println("threadA begin wait");                    resourceA.wait();                    System.out.println("threadA end wait");                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    });    Thread threaB = new Thread(new Runnable() {        @Override        public void run() {            synchronized (resourceA) {                System.out.println("threadC begin notify");                threadA.interrupt();                System.out.print(resourceA);                resourceA.notify();            }        }    });    threadA.start();    Thread.sleep(1000);    threaB.start();    System.out.println("main over");}}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java