synchronzied底层原理
synchronzied四个层级实现
- Java代码 通过添加synchronzied给对象或者方法或者代码块
- 字节码层级通过一组 MONITORENTER/MONITOREXIT指令
- JVM层级:锁升级过程
- 汇编执行通过 lock comxchg指令保证原子操作
JDK早期,synchronized 叫做重量级锁, 因为申请锁资源必须通过kernel, 系统调用
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | ;hello.asm;write(int fd, const void *buffer, size_t nbytes)
 
 section data
 msg db "Hello", 0xA
 len equ $ - msg
 
 section .text
 global _start
 _start:
 
 mov edx, len
 mov ecx, msg
 mov ebx, 1 ;文件描述符1 std_out
 mov eax, 4 ;write函数系统调用号 4
 int 0x80
 
 mov ebx, 0
 mov eax, 1 ;exit函数系统调用号
 int 0x80
 
 | 
优化后的synchronized如下👇:
Java层级
| 12
 3
 4
 5
 6
 7
 8
 
 | public static void main(String[] args) {Object object = new Object();
 System.out.println(ClassLayout.parseInstance(object).toPrintable());
 
 synchronized (object){
 System.out.println(ClassLayout.parseInstance(object).toPrintable());
 }
 }
 
 | 
字节码层级
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 
 | public static main([Ljava/lang/String;)V
 
 TRYCATCHBLOCK L0 L1 L2 null
 TRYCATCHBLOCK L2 L3 L2 null
 L4
 LINENUMBER 13 L4
 NEW java/lang/Object
 DUP
 INVOKESPECIAL java/lang/Object.<init> ()V
 ASTORE 1
 L5
 LINENUMBER 14 L5
 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
 ALOAD 1
 INVOKESTATIC org/openjdk/jol/info/ClassLayout.parseInstance (Ljava/lang/Object;)Lorg/openjdk/jol/info/ClassLayout;
 INVOKEVIRTUAL org/openjdk/jol/info/ClassLayout.toPrintable ()Ljava/lang/String;
 INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
 L6
 LINENUMBER 16 L6
 ALOAD 1
 DUP
 ASTORE 2
 MONITORENTER
 L0
 LINENUMBER 17 L0
 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
 ALOAD 1
 INVOKESTATIC org/openjdk/jol/info/ClassLayout.parseInstance (Ljava/lang/Object;)Lorg/openjdk/jol/info/ClassLayout;
 INVOKEVIRTUAL org/openjdk/jol/info/ClassLayout.toPrintable ()Ljava/lang/String;
 INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
 L7
 LINENUMBER 18 L7
 ALOAD 2
 MONITOREXIT
 L1
 GOTO L8
 L2
 FRAME FULL [[Ljava/lang/String; java/lang/Object java/lang/Object] [java/lang/Throwable]
 ASTORE 3
 ALOAD 2
 MONITOREXIT
 L3
 ALOAD 3
 ATHROW
 L8
 LINENUMBER 19 L8
 FRAME CHOP 1
 RETURN
 L9
 LOCALVARIABLE args [Ljava/lang/String; L4 L9 0
 LOCALVARIABLE object Ljava/lang/Object; L5 L9 1
 MAXSTACK = 2
 MAXLOCALS = 4
 }
 
 | 
主要通过MONITORENTER 和 MONITOREXIT 两个字节码指令控制加锁过程
JVM层级
通过锁升级过程实现加锁;
无锁 -> 偏向锁 -> 自旋锁(轻量级锁 自适应锁)-> 重量级锁
锁升级过程可以查看 锁升级过程  复制理解
汇编指令级别
linux操作系统安装hsdis插件,查看java代码的汇编指令:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | public class T {static volatile int i = 0;
 
 public static void n() { i++; }
 
 public static synchronized void m() {}
 
 publics static void main(String[] args) {
 for(int j=0; j<1000_000; j++) {
 m();
 n();
 }
 }
 }
 
 | 
执行以下命令:
| 1
 | java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly T
 | 
- C1 Compile Level 1 (一级优化)
- C2 Compile Level 2 (二级优化)
找到m() n()方法的汇编码,会看到 lock comxchg …..指令