摘要
synchronized是java的关键字,也可以叫同步锁,能够保证在同一时刻最多只有一个线程执行同步代码代码块,以达到保证并发安全的效果。
性质
可重入性:当一个线程获取锁后,没有释放当前锁,再次获取当前锁时,可以直接进去,不需要再次获取锁,synchronized可以是一个悲观锁,独占锁。
原子性:确保同一时间只有一个线程能拿到锁,能够进入代码块。
不可中断性:一个线程获取锁之后,另外一个线程处于阻塞或者等待状态,前一个不释放,后一个也一直会阻塞或者等待,不可以被中断。
synchronized的三种使用场景
1.作用于普通方法上,表示this锁
public synchronized void run() {}
2.作用于静态方法上,表示锁的是class字节码
public synchronized static void run() {}
3.还可以自定义锁对象
Object o = new Object();
public void add() {
synchronized (o){
//处理任务逻辑
}
}
synchronized的底层原理
测试类如下:
public class Test003 {
public synchronized void add() {
synchronized (new Object()) {
}
}
}
通过编译后,我们进入class文件目录查看class文件,javap -p -v -c Test003.class 这里提供一部分
public Thread.Test003();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 7: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LThread/Test003;
public void add();
descriptor: ()V
flags: ACC_PUBLIC ACC_SYNCHRONIZED //标志位
Code:
stack=2, locals=3, args_size=1
0: new #2 // class java/lang/Object
3: dup
4: invokespecial #1 // Method java/lang/Object."<init>":()V
7: dup
8: astore_1
9: monitorenter //进去该方法,白话获取锁
10: aload_1
11: monitorexit //执行结束,正常退出
12: goto 20
15: astore_2
16: aload_1
17: monitorexit //发生异常,异常捕获退出
18: aload_2
19: athrow
20: return
我们可以看到反编译后,由monitor对象来控制,
当我们进入方法的时候,执行monitorenter,就会获取当前对象的所有权,这个时候monitor进入数为1,当前的这个线程就是这个monitor的owner。
如果你已经是这个monitor的owner了,你再次进入,就会把进入数+1,当他执行完monitorexit,对应的进入数就-1,直到为0,才可以被其他线程持有,
标志位ACC_SYNCHRONIZED的作用
同步方法的时候,一旦执行到这个方法,就会先判断是否有标志位,然后ACC_SYNCHRONIZED会去隐式调用两个指令:monitorenter和monitorexit
为什么有两个monitorexit
第一个是正常结束退出,第二个是异常捕获退出,都会释放当前锁。
锁的升级
了解锁的升级过程先了解下对象的组成,对象一般由对象头,实例数据,填充数据组成,对象头由Mark Word,对象指针,数组长度组成。
Mark Word的构成:64位操作系统
锁的升级流程:
当线程获取锁的时候,会首先判断当前线程是否是同一个线程,如果是当前线程的话,会判断当前线程是否获取过锁,如果没有获取到标志位修改为,获取到标志位+1。在对象头中的markwork中是否持有偏向锁也更新为1,也就是我们所说的偏向锁。如果不是当前线程的话,升级为轻量级锁。jvm会在当前线程的栈帧中建立一个叫锁记录的空间,用来存储锁对象的Mark Word 拷贝,然后把Lock Record中的owner指向当前对象,通过cas操作如果修改成功获取锁成功,修改失败的话会短暂尝试一段时间,如果还是获取锁失败的话,继续升级为重量级锁。
**
synchronized关键字的知识就总结这么多,如有错误请留言指出,谢谢!!!
**