Java主流锁体系全面认识:
- 1、乐观锁,悲观锁
- 2、读锁(共亨锁),写锁(排它锁)
- 3、自旋锁,非自旋锁
- 4、无锁,偏向锁,轻量级锁,重量级锁
- 5、分布式锁
- 6、区间锁(分段锁)java.util. concurrent ConcurrentHashMap
- 7、重入锁、非重入锁
- 8、公平锁、非公平锁







- 如果自旋锁一直拿不到资源,那么会挂起该线程或者抛出异常


- synchronized是通过Monitor(监视器锁)实现的,监视器对象Monitor通过其monitorenter和moniterexit方法来对代码块进行同步,而这些方法都是依赖的OS底层的Mutex lock(互斥锁)来实现的


- 锁的膨胀升级是不可逆的,因为升级到重量级锁之后,就是Synchronized使用OS底层互斥锁来进行加锁,这个过程直到该线程完成了对临界区的访问。访问完之后就释放锁了,这时候临界区是一个无锁的状态,所以整个过程不可逆,是一个循环的过程(一个周期)。
- Synchronized是隐式锁,其是基于JVM的内置锁,加锁和解锁的过程不需要我们在代码中人为控制,JVM会自动加锁和解锁。ReentrantLock是显式锁,通过AQS实现,加锁和解锁的过程需要手动控制。AQS(AbstractQueuedSynchronizer)
- Synchronized和所有实现了Lock接口的都是悲观锁
Synchronized底层优化:

面试题:实例对象是怎么存储的?
- 对象的实例存储在堆中
- 对象的引用存储在栈中
- 对象的元数据存储在方法区(元空间/永久代)

Q:为什么不直接上重量级锁?
A:上重量级锁会涉及到线程的上下文切换,会涉及到OS用户态到内核态的切换,非常消耗资源
线程的上下文切换耗费资源:
- JVM是运行在OS上面的,他无法操作OS,其是运行在用户态的程序,所以他要向OS请求切换到内核态,让CPU创建新的时间片来处理JVM的新线程。CPU运行时的一些中间变量都是保存在寄存器的,所以切换线程时,老的线程的一些信息就需要回写到内存中线程对应的进程中的PCB中。然后CPU加载新线程,新线程运行完,再从PCB的阻塞队列唤醒老的线程,CPU重新加载其Context,然后再运行老线程。
- 现代os都将线程作为最小调度单位,进程作为资源分配的最小单位,所以说单核CPU线程之前是并发而不是并行。
AQS原理:

知识点:
ReentrantLock是可重入锁,底层是有AQS实现,AQS有四个重要的属性:head、tail、state、exclusiveOwnerThread
- head:CLH的队头
- tail:CLH的队尾
- state:当前可重入锁加锁的次数
- exclusiveOwnerThread:当前获得锁的线程
使用CAS算法来循环判断state是否为0:
- 如果为0则获得锁
- 如果不为0则加入CLH队列
- 如果state不为0且CLH队列满,则报错
注意:加入CLH队列的顺序通过指定公平锁和非公平锁来决定,非公平锁会先使用CAS看一下state是否为0,如果是的话就获得锁,而不是先进入CLH进行排队


- 注意:ArrayBlockQueue是一个条件队列
网友评论