Java线程转储:“等待locking”和“停车等待”之间的区别?
在Java线程转储中,您可以看到堆栈跟踪中提到的锁。
似乎有三种信息:
1:
- locked <0x00002aab329f7fa0> (a java.io.BufferedInputStream)
2:
- waiting to lock <0x00002aaaf4ff6fa0> (a org.alfresco.repo.lock.LockServiceImpl)
3:
- parking to wait for <0x00002aaafbf70bb8> (a java.util.concurrent.SynchronousQueue$TransferStack)
- 1:线程已获得对象0x00002aab329f7fa0的locking。
- 2&3:似乎说线程正在等待所述对象的locking变为可用…
但是2和3有什么区别?
在使用内部锁时,您将在“线程转储”中“等待locking”,并在使用java.util.concurrent的锁时获得“停车等待”。 考虑下面的例子:
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockTest { final Lock lock = new ReentrantLock(true); synchronized void intrinsicLock() { Thread th = new Thread(new Runnable() { public void run() { intrinsicLock(); } }, "My thread"); th.start(); try { th.join(); } catch (InterruptedException e) { } } void reentrantLock() { lock.lock(); Thread th = new Thread(new Runnable() { public void run() { reentrantLock(); } }, "My thread"); th.start(); try { th.join(); } catch (InterruptedException e) { } lock.unlock(); } public static void main(String[] args) { LockTest lockTest = new LockTest(); lockTest.intrinsicLock(); //lockTest.reentrantLock(); } }
使用lockTest.intrinsicLock()
您将获得以下线程转储:
"My thread" prio=10 tid=0x00007fffec015800 nid=0x1775 waiting for monitor entry [0x00007ffff15e5000] java.lang.Thread.State: BLOCKED (on object monitor) at LockTest.intrinsicLock(LockTest.java:9) - waiting to lock <0x00000007d6a33b10> (a LockTest) at LockTest$1.run(LockTest.java:11) at java.lang.Thread.run(Thread.java:662)
而lockTest.reentrantLock()
产生:
"My thread" prio=10 tid=0x00007fffec082800 nid=0x17e8 waiting on condition [0x00007ffff14eb000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00000007d6a33d30> (a java.util.concurrent.locks.ReentrantLock$FairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:842) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1178) at java.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.java:201) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262) at LockTest.reentrantLock(LockTest.java:22) at LockTest$2.run(LockTest.java:25) at java.lang.Thread.run(Thread.java:662)
在我看来,java.util.concurrent包几乎都使用LockSupport.park()方法来阻塞线程,如CountDownLatch,ReentrantLock等属于abstractqueueds的同步框架。 因此,在你的问题中的第三个场景意味着你的代码最终调用LockSupport.park()方法,因为你使用java.util.concurrent包中的并发类,第二个场景意味着你明确使用同步的keywork和调用wait()方法。