标签:upd time method amp font dep dia rup dde
public class MultInterruptParkDemo { public static volatile boolean flag = true; public static void main(String[] args) { ThreadDemo04 t4 = new ThreadDemo04(); t4.start(); t4.interrupt(); flag = false; } public static class ThreadDemo04 extends Thread { @Override public void run() { while (flag) { } LockSupport.park(); System.out.println("本打印出现在第一个park()之后"); LockSupport.park(); System.out.println("本打印出现在第二个park()之后"); } } }
结果:
本打印出现在第一个park()之后 本打印出现在第二个park()之后
Thread中断方法分析(包括HotSpot源码)中interrupt源码:
void os::interrupt(Thread* thread) { assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); OSThread* osthread = thread->osthread(); if (!osthread->interrupted()) { osthread->set_interrupted(true);
如果线程未设置中断标志位,会进行设置。
LockSupport及HotSpot层Parker::park/unpark分析中park源码:
void Parker::park(bool isAbsolute, jlong time) { // Ideally we‘d do something useful while spinning, such // as calling unpackTime(). // Optional fast-path check: // Return immediately if a permit is available. // We depend on Atomic::xchg() having full barrier semantics // since we are doing a lock-free update to _counter. if (Atomic::xchg(0, &_counter) > 0) return; Thread* thread = Thread::current(); assert(thread->is_Java_thread(), "Must be JavaThread"); JavaThread *jt = (JavaThread *)thread; // Optional optimization -- avoid state transitions if there‘s an interrupt pending. // Check interrupt before trying to wait if (Thread::is_interrupted(thread, false)) { return; }
只要线程设置了中断标志位,就直接返回,且这里的Thread::is_interrupted(thread, false)因为是false,所以不会清除中断标志位。
public class MultInterruptParkDemo2 { public static volatile boolean flag = true; public static void main(String[] args) { ThreadDemo04 t4 = new ThreadDemo04(); t4.start(); LockSupport.unpark(t4); LockSupport.unpark(t4); LockSupport.unpark(t4); flag = false; } public static class ThreadDemo04 extends Thread { @Override public void run() { while (flag) { } LockSupport.park(); System.out.println("本打印出现在第一个park()之后"); LockSupport.park(); System.out.println("本打印出现在第二个park()之后"); } } }
结果:
本打印出现在第一个park()之后
LockSupport及HotSpot层Parker::park/unpark分析中park源码:
void Parker::park(bool isAbsolute, jlong time) { // Ideally we‘d do something useful while spinning, such // as calling unpackTime(). // Optional fast-path check: // Return immediately if a permit is available. // We depend on Atomic::xchg() having full barrier semantics // since we are doing a lock-free update to _counter. if (Atomic::xchg(0, &_counter) > 0) return;
每次调用park都会将_counter直接置为0。
void Parker::unpark() { int s, status ; status = pthread_mutex_lock(_mutex); assert (status == 0, "invariant") ; s = _counter; _counter = 1;
每次调用unpark都会将_counter直接置为1.
public class MultInterruptParkDemo3 { public static volatile boolean flag = true; public static void main(String[] args) { ThreadDemo04 t4 = new ThreadDemo04(); t4.start(); t4.interrupt(); flag = false; } public static class ThreadDemo04 extends Thread { @Override public void run() { while (flag) { } LockSupport.park(); System.out.println("本打印出现在第一个park()之后"); System.out.println(Thread.interrupted()); System.out.println(Thread.interrupted()); LockSupport.park(); System.out.println("本打印出现在第二个park()之后"); } } }
结果:
本打印出现在第一个park()之后 true false
Thread中断方法分析(包括HotSpot源码)中Thread.interrupted()源码:
public static boolean interrupted() { return currentThread().isInterrupted(true); }
bool os::is_interrupted(Thread* thread, bool clear_interrupted) { assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); OSThread* osthread = thread->osthread(); bool interrupted = osthread->interrupted(); if (interrupted && clear_interrupted) { osthread->set_interrupted(false); // consider thread->_SleepEvent->reset() ... optional optimization } return interrupted; }
可以看到如果中断了并且clear_interrupted为true,则会清除中断标志位。
Thread.interrupted()清除中断标志位后,第二个LockSupport.park()就不会直接返回,而是正常地阻塞。
public class MultInterruptParkDemo4 { public static volatile boolean flag = true; public static void main(String[] args) { ThreadDemo04 t4 = new ThreadDemo04(); t4.start(); t4.interrupt(); flag = false; } public static class ThreadDemo04 extends Thread { @Override public void run() { while (flag) { } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("本打印出现在第一个sleep()之后"); System.out.println(Thread.interrupted()); System.out.println(Thread.interrupted()); LockSupport.park(); System.out.println("本打印出现在第二个park()之后"); } } }
结果
java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at wz.interrupt.MultInterruptParkDemo4$ThreadDemo04.run(MultInterruptParkDemo4.java:19) 本打印出现在第一个sleep()之后 false false 本打印出现在第二个park()之后
Thread中断方法分析(包括HotSpot源码)中interrupt源码:
void os::interrupt(Thread* thread) { assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); OSThread* osthread = thread->osthread(); if (!osthread->interrupted()) { osthread->set_interrupted(true); // More than one thread can get here with the same value of osthread, // resulting in multiple notifications. We do, however, want the store // to interrupted() to be visible to other threads before we execute unpark(). OrderAccess::fence(); ParkEvent * const slp = thread->_SleepEvent ; if (slp != NULL) slp->unpark() ; } // For JSR166. Unpark even if interrupt status already was set if (thread->is_Java_thread()) ((JavaThread*)thread)->parker()->unpark(); ParkEvent * ev = thread->_ParkEvent ; if (ev != NULL) ev->unpark() ; }
会调用Parker::unpark(),那么_counter会设置为1.
参考阻塞线程的相关方法分析(包括HotSpot层源码)中关于sleep源码:
JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis)) JVMWrapper("JVM_Sleep"); if (millis < 0) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); } if (Thread::is_interrupted (THREAD, true) && !HAS_PENDING_EXCEPTION) { THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted"); }
如果线程已中断,则清除中断标记并抛出中断异常,直接返回,但是并没有更改_counter。
如下两个条件任何一个成立,park()都不会阻塞:
作者:王侦
链接:https://www.jianshu.com/p/d48f854ead85
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
interrupt()中断对LockSupport.park()行为影响
标签:upd time method amp font dep dia rup dde
原文地址:https://www.cnblogs.com/septemberFrost/p/12200755.html