
Java 锁
Java 中锁分为两类:
- 第一类是 synchronized 同步关键字,这个关键字属于隐式的锁,是 JVM 层面实现,使用的时候看不见。
- 第二类是在 JDK5 后添加的 Lock 接口以及对应的各种实现类,这属于显式的锁,这就是我们能在代码层面看到锁这个对象,而这些对象的方法实现,大都是直接依赖 CPU 指令,与 JVM 无关。
Synchronized
使用
- 如果修饰的是
具体对象
:锁的是对象
- 如果修饰的是
成员方法
:锁的是this
- 如果修饰的是
静态方法
:锁的是对象.class
synchronized 修饰方法
public class Tuse {
public static int i;
public synchronized static void syncTask() {
i ++;
}
}
synchronized 代码块
public class Tues {
public int i;
public void syncTask() {
synchronized (this) {
i ++;
}
}
}
类型
- 偏向锁:这个锁会偏向于第一个获得它的线程,当这个线程再次请求锁的时候不需要进行任何同步操作。
- 自旋锁:自旋锁是一个过度锁,是从轻量级到重量级锁的过渡。也就是 CAS
- 轻量级锁:当偏向锁的条件不满足,或有多个线程并发争抢同一锁对象时,优先使用轻量级锁
- 重量级锁:重量级锁具有完整
Monitor
功能的锁
Lock
Lock 是一个接口,实现类常见的有:
- 重入锁(
ReentrantLock
) - 读锁(
ReadLock
) - 写锁(
WriteLock
)
实现基本都是通过聚合了一个同步器(AbstractQueuedSynchronizer
缩写为AQS
)的子类来完成线程访问控制的。
AbstractQueuedSynchronizer
队列同步器,是用来构建锁或者其他同步组件的基础框架,它使用了一个 int 成员变量表示同步状态,通过内置的 FIFO 队列来完成资源获取线程的排队工作。
同步器的主要使用方法是继承,子类通过同步器并实现它的抽象方法来管理同步状态,在抽象方法的实现过程中免不了对同步状态的更改,这时需要使用同步器提供的 3 个方法来进行操作。三个方法分别是:
protected final int getState()
获取当前同步状态。protected final void setState(int newState)
设置当前同步状态。protected final bool compareAndSetState()
使用 CAS 设置当前状态。
重入锁 ReentrantLock
- 支持一个线程对资源重复加锁。
- 支持获取锁时的公平和非公平性选择。