CAS
compare and swap
比较交换操作,乐观锁的表现方式;
- 首次操作会读取内存中的值作为参考值,当我们完成相关操作后,再次获取内存中的值对比,如果不一致,那么我们读取最新的值,再次尝试操作;
- 底层使用unsafe类compareAndSwapInt 等方法实现
- 适用于少量并发,会造成cpu消耗问题
- 会有ABA问题
锁的分类
- 乐观锁、悲观锁
CAS乐观锁、synchronize悲观锁
- 可重入锁
A方法与B方法都是同步方法、A中调用B,可能造成死锁
synchronize已经实现了可重入
- 偏向锁、轻量级锁、重量级锁
锁的状态信息
存在锁对象的的对象头的mark word中
- 偏向锁:如果只有一个线程访问,那么直接获得锁;
- 轻量级锁:如果已经是偏向锁状态,多个线程没有获得执行,那么不会进入阻塞,操作系统仍然在调度,等待被执行;
- 重量级锁:轻量级锁状态下,长时间没有获得执行,膨胀为重量级锁,进入阻塞,操作系统将不再调度,只能再次等待被调度;
- 读写锁
读读不互斥、读写互斥、写写互斥
- 独占锁、共享锁
如readwritelock读写锁,读读共享,读写独占;
- 自旋锁
CAS操作就是不断的比较尝试
- 分段锁
一种思想,我们应该只锁部分代码块而非整个方法
- 公平锁、非公平锁
ReentrantLock默认非公平,构造时传入true就是公平锁
synchronize为非公平锁
AQS
concurrent并发包的许多方法都是基于AQS实现
我们可以看到ReentrantLock锁就是基于AQS实现
private final Sync sync;
/**
* Base of synchronization control for this lock. Subclassed
* into fair and nonfair versions below. Uses AQS state to
* represent the number of holds on the lock.
*/
abstract static class Sync extends AbstractQueuedSynchronizer
sync其中的非公平锁
非公平锁会先尝试竞争锁,如果竞争不到才会排队等待锁
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
sync其中的公平锁
公平锁排队等待锁
/**
* Sync object for fair locks
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
公平锁和非公平锁的排队等待锁
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}