synchronized关键字可以实现什么类型的锁?
- 悲观锁:
synchronized
关键字实现的是悲观锁,每次访问共享资源时都会上锁。 - 非公平锁:
synchronized
关键字实现的是非公平锁,即线程获取锁的顺序并不一定是按照线程阻塞的顺序。 - 可重入锁:
synchronized
关键字实现的是可重入锁,即已经获取锁的线程可以再次获取锁。 - 独占锁或者排他锁:
synchronized
关键字实现的是独占锁,即该锁只能被一个线程所持有,其他线程均被阻塞。 -
轻量级锁
1.轻量级锁:如果一个对象虽然有多线程访问,但多线程访问的时间是错开的(也就是没有竞争),那么可以用轻量级锁来优化
-
创建锁记录对象,每个线程的栈帧都会包含一个所记录的结构,内存可以存储锁定对象的mark word
-
让锁记录的object reference指向锁对象,并尝试用cas替换object的mark word,将mark word的值存入锁记录
-
如果cas替换成功,对象中存储了所记录地址和状态00,表示由该线程给对象加锁
-
如果cas失败,有两种情况:
- 如果是其他线程持有了该object的轻量级锁,这时表明有竞争,进入锁膨胀过程
- 如果是自己执行了synchronized锁重入,那么再添加一条lock record作为重入的计数
-
- 当退出代码块的时候(解锁时)如果有取值为null的锁记录,表示有重入,这时重置锁记录,表示重入计数减一
- 当退出代码块的时候(解锁时)取值不为null,这时使用cas把mark word的值恢复给对象头,成功则解锁成功,失败说明轻量级锁进行了锁膨胀或已经升级为重量级锁,进入重量级锁解锁过程
如果尝试加轻量级锁的过程,cas操作无法成功,这是一种情况就是其他线程对此对象加上了轻量级锁(有竞争),这时需要锁膨胀,将轻量级锁变成重量级锁
当退出时会cas失败,然后进入到monitor中将owner设置为null,韩星entrylist的blocked线程
偏向锁
一个对象创建时默认开启偏向锁
撤销:调用了对象的hashcode,但偏向锁的对象markword中存储是线程id,如果掉桶hashcode会导致偏向锁被撤销
- 轻量级锁会在锁记录中记录hashcode
- 重量级会在monitor中存储
批量重偏向
如果对象虽然被多个线程访问,但没有竞争,这是偏向了t1的对想仍有机会重新偏向t2,重偏向会重新设置对象的thread id
当撤销偏向锁阙值超过20次,jvm就会这样觉得,我是不是偏向错了呢,于是会在给这些对象加锁时重新偏向至加锁线程
批量撤销
当撤销偏向到达四十次,于是整个类的所有对象都会变成不可偏向的,新建的对象也是不可偏向的
锁撤销
当编译器认为没有多线程竞争的时候就会把锁消除进行优化
,重偏向会重新设置对象的thread id
当撤销偏向锁阙值超过20次,jvm就会这样觉得,我是不是偏向错了呢,于是会在给这些对象加锁时重新偏向至加锁线程
批量撤销
当撤销偏向到达四十次,于是整个类的所有对象都会变成不可偏向的,新建的对象也是不可偏向的
锁消除
当编译器认为没有多线程竞争的时候就会把锁消除进行优化