并发编程,尤其是Java编程中经常涉及到锁的概念。我们听过乐观锁/悲观锁、公平锁/非公平锁、独享锁/共享锁、自旋锁等等,新手看到这么多锁的类别不免眼花缭乱,心中生怯。事实上,掌握Java中的锁只需要把握两个关键概念——synchronized关键字和Lock接口。
在JDK 1.5之前,synchronized是Java唯一的加锁方式,在之后的版本中才加入的Lock接口。
那么,sychronized和Lock跟上面提到的诸多类型的锁是什么关系呢?下面我们来逐个看各种锁的概念。
1.公平锁/非公平锁
多个申请锁的线程是否能按照申请顺序获取锁
Synchronized是非公平锁;
ReentrantLock是Lock接口的实现,默认是非公平锁,但支持实现公平锁(ReentrantLock有两个构造函数,可选择初始化为公平锁,底层都是依赖AbstractQueuedSynchronizer)
2.乐观锁/悲观锁
Synchronized和Lock都是悲观锁——所有独占资源的锁都是悲观锁;
ReentrantLock是一种悲观锁设计,但其底层锁获取是使用CAS算法(一种乐观锁实现算法)实现的;
乐观锁的典型应用是原子类如AtomicInteger
3.独享锁/共享锁
锁是否支持被多个线程持有
Synchronized和ReentrantLock都是独享锁, ReentrantReadWriteLock是另一个接口ReadWriteLock的实现,而ReadWriteLock包含了两个Lock成员,一个作为读锁,一个作为写锁,其读锁是共享锁,其写锁是独享锁
4.可重入锁
获取外层方法锁之后内层方法是否自动获取锁
Synchronized和Lock都是可重入的
5.偏向锁
synchronize在1.6版本之后提供的一种功能,以达到在锁竞争不激烈的情况下减少线程切换的目的。通过在栈帧和对象头里记录获取锁的线程ID,并校验尝试获取锁的线程ID的方式来决定是否允许线程获取锁。
6.轻量级锁
存在锁竞争的情况下,偏向锁会变成轻量级锁,轻量级锁不blocked线程,而是使用自旋来获取锁,这就是【轻量】的含义。
7.重量级锁
轻量级锁解锁失败会使锁膨胀为重量级锁。即我们熟悉的会阻塞线程的synchronize。
如有错误请指正…