ReentrantLock
概念
继承AQS,实现Lock,实现由内部类子类Sync的实现类FairSync和NonFairSync实现公平锁和非公平锁
获取锁
尝试快速获取锁,如果获取失败,则调用acquire(int arg)方法
调用tryAcquire(int arg)方法
逻辑:首先判断同步状态state == 0 ?,如果是表示该锁还没有被线程持有,直接通过CAS获取同步状态,如果成功返回true。如果state != 0,则判断当前线程是否为获取锁的线程,如果是则获取锁,成功返回true。成功获取锁的线程再次获取锁,这是增加了同步状态state。
释放锁
Sync的release(int arg)释放锁
调用tryRelease(int arg)
只有当同步状态彻底释放后该方法才会返回true。当state == 0 时,则将锁持有线程设置为null,free= true,表示释放成功
公平锁与非公平锁
获取锁的时候是否按照FIFO的顺序来。释放锁不存在公平性和非公平性
ReentrantLock与synchronized区别
相同点
可重入锁
加锁方式同步,而且都是阻塞式的同步
不同点
加锁解锁方式(ReentrantLock手动,synchronized由jvm自动)
灵活性(ReentrantLock更灵活)
是否等待可中断(ReentrantLock可中断)
公平锁(ReentrantLock都可以,synchronized非公平锁)
条件condition(ReentrantLock支持)
获取线程状态(ReentrantLock提供)
使用场景
synchronized:资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的
ReentrantLock提供了多样化的同步,在资源竞争不激烈的情形下,性能稍微比synchronized差点点。当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态
CAS
概念
CAS中有三个参数:内存值V、旧的预期值A、要更新的值B,当且仅当内存值V的值等于旧的预期值A时才会将内存值V的值修改为B,否则什么都不干。
atomic类原理
概念:valueOffset为变量值在内存中的偏移地址,unsafe就是通过偏移地址来得到数据的原值的。
AtomicInteger
addAndGet()方法
unsafe.getAndAddInt
compareAndSwapInt
CAS缺陷
循环时间太长
只能保证一个共享变量原子操作
ABA问题
解决方法:版本号,Java提供了AtomicStampedReference来解决
并发工具类
CountDownLatch
在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待
CyclicBarrier
它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)
Semaphore
一个控制访问多个共享资源的计数器
Exchanger
对元素进行配对和交换的线程的同步点
ThreadLocal
原理
ThreadLocalMap实现
内部利用Entry来实现key-value的存储,Entry实现WeakReference(弱引用)
ThreadLocal为什么会内存泄漏
key为ThreadLocal为弱引用,当key==null,就会回收,但是value却不是弱引用,还有强引用关系,不能回收,所以导致内存泄漏