同时执行 Thread.interrupt() Object.notify() 为什么会有两个结果?
execute Thread.interrupt() Object.notify() at the same time, why does has two results?
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");
}
}
这里有两种可能的结果:
抛出 InterruptedException
正常终止
为什么?
我不明白。当 threadA 被中断时,结果应该抛出 InterruptedException。但是有时候执行这个程序,可以正常结束。
环境: java8, mac
因为重新排序。在正常终止编译器重新排序指令中断和通知,中断在工作线程上调用并且没有中断异常抛出。
尝试通过读取 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");
}
}
当线程同时收到中断和通知时,行为可能会有所不同。
请参考https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.2.3
致谢 - Alex Otenko 在 Concurrency Interest 邮件列表中
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");
}
}
这里有两种可能的结果:
抛出 InterruptedException
正常终止
为什么?
我不明白。当 threadA 被中断时,结果应该抛出 InterruptedException。但是有时候执行这个程序,可以正常结束。
环境: java8, mac
因为重新排序。在正常终止编译器重新排序指令中断和通知,中断在工作线程上调用并且没有中断异常抛出。 尝试通过读取 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");
}
}
当线程同时收到中断和通知时,行为可能会有所不同。
请参考https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.2.3
致谢 - Alex Otenko 在 Concurrency Interest 邮件列表中