java进阶(5)之ReentranctLock/AQS等并发原理解析

PS: AQS全称AbstractQueueSynchronizer,抽象队列同步器,是并发中最核心的一个类了,本篇文章不剖析源码,只用文字和图形表达。

AQS解析以及与ReentranctLock之间的关系

在这里插入图片描述
通过看源码可知,ReentranctLock关于锁的操作,都是基于AQS的。
AQS中有两个核心的属性,状态变量state和双向链表headtail
state用于保存当前是否有锁以及锁的种类(读or写),默认值为0,通过VarHandle.compareAndSet(this, expect, update),来改变字段值(这个就是传说中的CAS操作,基于底层操作系统,能保证原子性)。JDK开发人员也巧妙地将int类型的state的高低16位,分别代表锁的读和写,从而能让一个参数,存储到读和写两个状态.

双向链表headtail,用于将阻塞的线程加入到队尾中,然后从队首取出阻塞的线程进行消费。

ReentrantReadWriteLock解析

在这里插入图片描述
其实跟ReentrantLock类似,只是ReentrantReadWriteLockReadLockWriteLock两把锁。说是两把锁,但是两个对象,都是使用的AQS中的锁,也就是通过state变量控制读写锁状态,并且通过AQS里内部算法实现:读写锁互斥,写写锁互斥,读读锁正常取值。

锁优化的策略

  • 标志位修改等可减刑场景优先使用volatile
  • 数值递增场景优先使用Atomic原子类
  • 数据允许多副本场景优先使用ThreadLocal
  • 读多写少需要加锁的场景优先使用读写锁
  • 尽可能减少线程对锁占用的时间
  • 尽可能减少线程对数据加锁的粒度
  • 尽可能对不同功能分离锁的使用
  • 避免在循环中频繁的加锁以及释放锁
  • 尽量减少高并发场景中线程对锁的争用
  • 采用多级缓存机制降低线程对锁对争用
  • 生产环境如遇死锁情况可用jstack进行分析