欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java-jvm-jstack-(监视器和锁的概念)

程序员文章站 2022-07-06 11:30:03
...

下面这段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)