synchronzied锁原理

Monitor

Monitor 被翻译为监视器或管程

每个 Java 对象都可以关联一个 Monitor 对象,Monitor 也是 class,其实例存储在堆中,如果使用 synchronized 给对象上锁(重量级)之后,该对象头的 Mark Word 中就被设置指向 Monitor 对象的指针,这就是重量级锁

  • Mark Word 结构:最后两位是锁标志位

    img

  • 64 位虚拟机 Mark Word:

    img

工作流程:

  • ​ 开始时Monitor中Owner 为 null
  • ​ 当Thread-2 执行了 synchronized(obj) 就会将 Monitor 的所有者 Owner 设置为 Thread-2, Monitor中只能有一个Owner, obj对象的Mark Word指向Monitor, 把对象原有的 MarkWord 存入线程的锁记录中

img

  • 在Thread-2 上锁的过程中, Thread-3, Thread-4 也执行了 synchronized 的时候, obj会再次的指向 Monitor 但是Thread-3 发现 Monitor 的 Owner 已经有人了,就会进入 EntryList 阻塞队列中,并进入Blocked 状态等待
  • 等Thread -2 执行完了同步代码块中的内容 , 根据obj对象头重的Monitor地址寻找,设置Owner为空 , 把线程的锁记录中的对象头的值设置会MarkWord
  • 最后会唤醒EntryList 阻塞队列中的线程来竞争锁,竞争是非公平的,是根据JDK底层的某些逻辑来决定唤醒顺序

img

注意:

  • synchronized 必须是进入同一个对象的 Monitor 才有上述的效果
  • 不加 synchronized 的对象不会关联监视器,不遵从以上规则
字节码

代码:

public static void main(String[] args) {
    Object lock = new Object();
    synchronized (lock) {
        System.out.println("ok");
    }
}
0: 	new				#2		// new Object
3: 	dup
4: 	invokespecial 	#1 		// invokespecial <init>:()V,非虚方法
7: 	astore_1 				// lock引用 -> lock
8: 	aload_1					// lock (synchronized开始)
9: 	dup						// 一份用来初始化,一份用来引用
10: astore_2 				// lock引用 -> slot 2
11: monitorenter 			// 【将 lock对象 MarkWord 置为 Monitor 指针】
12: getstatic 		#3		// System.out
15: ldc 			#4		// "ok"
17: invokevirtual 	#5 		// invokevirtual println:(Ljava/lang/String;)V
20: aload_2 				// slot 2(lock引用)
21: monitorexit 			// 【将 lock对象 MarkWord 重置, 唤醒 EntryList】
22: goto 30
25: astore_3 				// any -> slot 3
26: aload_2 				// slot 2(lock引用)
27: monitorexit 			// 【将 lock对象 MarkWord 重置, 唤醒 EntryList】
28: aload_3
29: athrow
30: return
Exception table:
    from to target type
      12 22 25 		any
      25 28 25 		any
LineNumberTable: ...
LocalVariableTable:
    Start Length Slot Name Signature
    	0 	31 		0 args [Ljava/lang/String;
    	8 	23 		1 lock Ljava/lang/Object;

说明:

  • 通过异常 try-catch 机制,确保一定会被解锁
    23 1 lock Ljava/lang/Object;



说明:

- 通过异常 **try-catch 机制**,确保一定会被解锁
- 方法级别的 synchronized 不会在字节码指令中有所体现
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值