一、为什么需要锁
在并发情况为了保证线程的安全性,是在一个多线程环境下正确性的概念,也就是保证多线程环境下共享的、可修改的状态的正确性(这里的状态指的是程序里的数据),在java程序中我们可以使用synchronized关键字来对程序进行加锁。
二、锁底层是怎么实现的?
synchronized(隐式锁)代码块的时候,编译成的字节码将包含monitorenter指令 和 monitorexit指令。这两种指令均会消耗操作数栈上的一个引用类型的元素(也就是 synchronized 关键字括号里的引用),作为所要加锁解锁的锁对象。
eg:
public class Test {
static task testDemo=new task();
public static void main(String[] args) {
synchronized (testDemo) {
System.out.println("lock ing");
}
}
static class task extends Thread {
@Override
public void run() {
System.out.println("run");
}
}
}
然后我们找到我们生成的class
## 运行指令查看字节码javap -c Test.class
Compiled from "Test.java"
public class jmm.Test {
static jmm.Test$task testDemo;
public jmm.Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field testDemo:Ljmm/Test$task;
3: dup
4: astore_1
5: monitorenter
6: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
9: ldc #4 // String lock ing
11: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
14: aload_1
15: monitorexit
16: goto 24
19: astore_2
20: aload_1
21: monitorexit
22: aload_2
23: athrow
24: return
Exception table:
from to target type
6 16 19 any
19 22 19 any
static {};
Code:
0: new #6 // class jmm/Test$task
3: dup
4: invokespecial #7 // Method jmm/Test$task."<init>":()V
7: putstatic #2 // Field testDemo:Ljmm/Test$task;
10: return
}
通过字节码可以看出包含一个monitorenter指令以及多个monitorexit指令。这是因为jvm需要确保所获得的锁在正常执行路径,以及异常执行路径上都能够被解锁。
三、锁升级过程
对象内存结构
对象头
不行了 写不动了 明天再写吧