下面这段jstack的栈信息里,有一个死锁
其中:
Thread-1 持有 0x00000007d5df4970,等待获取:0x00000007d5df4960
Thread-0 持有 0x00000007d5df4960,等待获取:0x00000007d5df4970
所以导致了死锁的出现
两个线程都有有一句: java.lang.Thread.State: BLOCKED (on object monitor)
表明:两个线程都阻塞在了 对应正在操作对象的object monitor上(是因为对象 被另外一个线程获加锁成功,并占有object monitor)
那object monitor 和 lock 有什么关系和区别?
1、object monitor 是任何一个对象都有的内置的数据结构,它是用来协调使用当前对象的多个线程之间的执行顺序的(wait/notify),线程会block或者wait 在一个对象的监视器上;锁是 对对象访问的时候,通过对对象加锁,防止并行访问的控制手段;
2、对 对象加锁成功,才能拿到 object monitor (对象监视器),如果加锁失败,会进入对象监视器的entry队列里:(monitor entry list),表现为: waiting for monitor entry,java.lang.Thread.State: BLOCKED (on object monitor)
3、对 对象枷锁成功,调用wait方法,也会wait 在object monitor上,但是会释放锁,并进入(monitor wait list),当前线程也就WAITING (on object monitor),表现为:java.lang.Thread.State: WAITING (on object monitor) 一旦对象被调用notify的,会重新尝试加锁,成功可以执行,否则进入(monitor entry list)
4、锁和监视器的关系:拿到对象的监视器,肯定是对对象加锁成功的;对对象加锁成功 ,程序可以主动Watiing或者Time_waiting在对象监视器上
线程使用对象的方式:
1、直接使用,为了避免多个线程同时使用,需要加锁,加锁成功的可以使用对象;
2、需要对象到达某种状态才能用,这时候需要调用对象的wait方法,线程挂起(wait)在对象的object monitor 监视器上,等待其他线程notify,可能多个线程都在wait,所以notify的时候多个等待的线程需要再次获取锁 ,这就解释了为什么wait的时候需要先加锁,notify的时候也需要加锁成功
总结:
线程,对象,锁,监视器的关系:线程里可以定义并访问对象,为了访问的安全性,需要对对象加锁,如果加锁失败,线程就会block,并进入( waiting for monitor entry),如果加锁成功,可以选择直接执行逻辑,如果需要获取其他线程执行的结果,当前线程就需要挂起(调用wait方法),线程进入java.lang.Thread.State: WAITING (on object monitor)状态,此时线程会释放锁,同时进入到monitor entry list;如果其他线程执行完成后进行notify,当前线程也就需要再次获取锁,并获取 object monitor,开始执行
C:\Users\xinchun.wang>jstack 15416
2017-04-06 12:22:03
Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.7-b01 mixed mode):
"DestroyJavaVM" prio=6 tid=0x000000000057f000 nid=0x3e98 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Thread-1" prio=6 tid=0x000000000d8af000 nid=0x1d1c waiting for monitor entry [0x000000000ddae000]
java.lang.Thread.State: BLOCKED (on object monitor)
at Test$T2.run(Test.java:161)
- waiting to lock <0x00000007d5df4960> (a java.lang.Object)
- locked <0x00000007d5df4970> (a java.lang.Object)
"Thread-0" prio=6 tid=0x000000000d8ae800 nid=0x790 waiting for monitor entry [0x000000000dcae000]
java.lang.Thread.State: BLOCKED (on object monitor)
at Test$T1.run(Test.java:136)
- waiting to lock <0x00000007d5df4970> (a java.lang.Object)
- locked <0x00000007d5df4960> (a java.lang.Object)
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x000000000252ee70 (object 0x00000007d5df4960, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x000000000252dac0 (object 0x00000007d5df4970, a java.lang.Object),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at Test$T2.run(Test.java:161)
- waiting to lock <0x00000007d5df4960> (a java.lang.Object)
- locked <0x00000007d5df4970> (a java.lang.Object)
"Thread-0":
at Test$T1.run(Test.java:136)
- waiting to lock <0x00000007d5df4970> (a java.lang.Object)
- locked <0x00000007d5df4960> (a java.lang.Object)