一、synchronized锁定的目标
![](https://img.haomeiwen.com/i6532223/4dff44bede7e768c.png)
如图所示,非常明了了,归根结底,synchronized锁定的既不是代码块、也不是一个方法,而是一个对象:方法锁锁定的是当前类的实例对象、静态方法锁锁定的是当前类的类对象、对象锁锁定的是目标对象、类锁锁定的是对应类的类对象。
为什么是这样呢?因为synchronized锁的信息保存在目标对象的对象头的markword中,当运行到synchronized代码的时候,JVM会读取被锁定对象的头部信息,以确定当前是否存在线程竞争。这时会触发synchronized的锁升级过程。
二、锁分类
公平锁/非公平锁
公平锁指的是线程按照申请顺序获取锁,非公平锁指线程不按照申请顺序获取锁。
synchronized是非公平锁。
可重入锁/不可重入锁
可重入锁指的是线程获取锁之后,在内部再次获取同一个锁时,不会发生死锁;不可重入锁反之。
synchronized是可重入锁。
乐观锁/悲观锁
乐观锁的思想是认为操作过程中数据不会被其他线程修改,只有在修改数据的时候才会进行判断,这点一般通过CAS实现。
悲观锁则总是假设最坏情况发生,所以每次操作的时候就会阻止其他线程执行相同操作,直到本线程执行完毕为止。
乐观锁、悲观锁并不是真正指的一种锁,而是一种思想。乐观锁常用于多读少写的场景,而悲观锁相反。
下面代码是乐观锁和悲观锁的示例,其中i++
模拟了事务的执行。
// 乐观锁
public void useOptimisticLock() {
while (true) {
final int oldI = i;
Transaction transaction = createTransaction(oldI);
// 模拟执行transaction
if (unsafe.compareAndSwapInt(this, I_OFFSET, oldI, oldI + 1)) {
return;
}
}
}
// 悲观锁
public void usePessimisticLock() {
synchronized (LOCK) {
Transaction transaction = createTransaction(i);
// 模拟执行transaction
i++;
}
}
参考资料
Oracle官方文档:synchronized
彻底理解synchronized
乐观锁 vs. 悲观锁
视频教程:马士兵Synchronized
网友评论