JUC(锁/并发容器/原子类/并发工具类)
2021-03-02 18:27:53 2 举报
AI智能生成
JUC(锁/并发容器/原子类/并发工具类)
作者其他创作
大纲/内容
阅读导航
线程 👉
CPU+JMM 👉
CAS+Volatile 👉
Synchronized 👉
JUC
locks锁+atomic原子类
executor自定义线程池 👉
collections并发容器 👉
tools并发工具类 👉
线程池 👉
ThreadLocal 👉
Lock 接口
ReentrantLock
原理:CAS+AQS 👉
请求线程先通过CAS尝试修改state状态位获取锁,如果没有获取到,就加入AQS队列
并且被挂起,当锁被释放之后, 排在队首的线程会被唤醒,通过CAS再次尝试获取锁
并且被挂起,当锁被释放之后, 排在队首的线程会被唤醒,通过CAS再次尝试获取锁
AQS
实现
独占锁
ReentrantLock
共享锁
CountDownLatch|CyclicBarrier|Semaphore
原理
AQS的实现依赖内部的同步队列,队列内部维护了一个state域和一个FIFO的双向链表,如果当前线程竞争锁(修改state状态)失败
那么AQS会把当前线程加入到同步队列中,同时阻塞该线程。当获取锁的线程释放锁以后,会从队列中唤醒队首的阻塞节点
那么AQS会把当前线程加入到同步队列中,同时阻塞该线程。当获取锁的线程释放锁以后,会从队列中唤醒队首的阻塞节点
公平与非公平
如果是非公平锁, 新进来的线程会尝试竞争锁,竞争不到才去排队;如果是公平锁,新来的线程会直接排到队尾,由队首的线程获取到锁
重入锁
现象:如果当前线程已经持有锁了,释放锁之前线程自己是可以重复获取此锁的(state会累加)这就是可重入的概念
但要注意获取多少次就要释放多少次,最后保证state能回到零态
但要注意获取多少次就要释放多少次,最后保证state能回到零态
原理:AQS的父类维护了一个属性,用来存储当前持有锁的线程ID,每次获取锁的时候对比线程ID看是否可重入
LockSupport
用于创建锁和其他同步类的基本线程阻塞原语,方法park()和unpark()提供了阻止和解除阻塞线程的有效手段
park():禁止当前线程进行线程调度,除非许可证可用
unpark(Thread thread):为给定的线程提供许可证(如果尚未提供)
Condition 接口
一个Condition实例本质上绑定到一个锁来使用,相当于一个队列,要获得特定Condition实例要调用 lock.newCondition();
await():使当前线程等待 发信号或 interrupted
signal():唤醒当前队列的一个等待线程
signalAll():唤醒所有等待线程
ReadWriteLock 接口
ReentrantReadWriteLock
读写锁维护着一对锁,一个读锁和一个写锁。通过分离读
锁和写锁,使得并发性比一般的排他锁有了较大的提升
锁和写锁,使得并发性比一般的排他锁有了较大的提升
在同一时间,可以允许多个读线程同时访问
在写线程访问时,所有读线程和写线程都会被阻塞
特点
公平性:支持公平锁和非公平锁
重入性:支持重入锁
锁降级:遵循获取写锁,再获取读锁,最后释放写锁的次序,如此写锁能够降级成为读锁
高频面试题
要求使用两个线程,交替打印出 1A2B3C4D5E6F7G
方式一:使用Lock结合Condition完成
方式二:使用LockSupport完成
ReentrantLock如何避免死锁?
响应中断 lockInterruptibly()
可轮询锁 tryLock()
定时锁 tryLock(long time)
lock和lockInterruptibly的区别?
lock 和 lockInterruptibly,如果两个线程分别执行这两个方法,但此时
中断这两个线程, lock 不会抛出异常,而 lockInterruptibly 会抛出异常
中断这两个线程, lock 不会抛出异常,而 lockInterruptibly 会抛出异常
tryLock和lock的区别?
tryLock 能获得锁就返回 true,不能就立即返回 false
lock 能获得锁就返回 true,不能的话一直等待获得锁
tryLock(long timeout,TimeUnit unit),可以增加
时间限制,如果超过该时间段还没获得锁,返回 false
时间限制,如果超过该时间段还没获得锁,返回 false
Synchronized和Lock的区别?
lock是接口,属于API层面,Synchronized是关键字,属于JVM层面
Synchronized是非公平锁,ReentrantLock两者都可以,默认非公平
Synchronized可以给方法和代码块加锁,lock只能给代码块加锁
ReentrantLock是自动释放锁,不会死锁;ReentrantLock需要手动释放锁
如果忘记unlock()则会出现死锁,所以我们一般会在finally中使用unlock()
如果忘记unlock()则会出现死锁,所以我们一般会在finally中使用unlock()
ReentrantLock更加灵活,结合Condition.signal(),可以给指定wait()对象解锁
atomic(原子类)
基本类型
AtomicBoolean
AtomicInteger
AtomicLong
基本类型数组
AtomicIntegerArray
AtomicLongArray
更新字段
AtomicIntegerFiledUpdater
AtomicLongFiledUpdater
AtomicReferenceFieldUpdater
引用类型
AtomicReference
AtomicMarkableReference
AtomicStampledReference
AtomicReferenceArray
累加器
LongAdder
DoubleAdder
LongAccumulator
DoubleAccumulator
关于作者
我的博客 👉
微信公众号 👉
GitHub 导航 👉
ProcessOn 主页 👉
0 条评论
下一页
为你推荐
查看更多