synchronized

2022/12/24

前言:此关键字是 java 的内置锁关键字,不需要开发者手动去加锁和解锁,加锁和解锁都是有 jvm 来负责,使用起来较为方便。

是否是可重入的? 是的。

通用流程

序号内容
1看到了锁,根据锁关联的对象,判断锁的级别 (实例级别、类级别)

书写的几种类型

修饰方法

修饰代码块

注意,synchronized 方法和 synchronized 代码块无论是执行 return 还是抛出异常,都一定能释放锁。因为不需要开发者显示去加锁、解锁,这些逻辑都被 jdk 给封装好了,开发者直接标识同步区域就好了。

如果锁代码块 则使用 monitorenter 和 monitorexit 来进入临界区和出临界区

如果修饰方法 在方法的 ACC_FLAG 中会存在 ACC_SYNCHRONIZED 标识。

一个问题,下面这个代码是否有问题

Integer i = 0;
synchronized(i) {
    i++; 
}

看起来也是锁的类成员变量。 但其实是有问题的,因为 i 每次都会变,所以这里锁的对象每次都是不同的,所以加锁也失去了意义。

i++ 实际是创建了一个新的 Integer 对象,i = Integer.valueOf(i.intValue() + 1)

解决方案:

  1. 使用原子变量 AtomicInteger 进行计数,这样就不用加锁。
  2. 使用专门的对象锁,另起一个锁对象。

永远不要锁可能改变引用的对象 锁对象应该是 final 的、不可变的