1.并发部分
1. AQS为什么是双向链表
2. 对AQS的理解?大致结构
3. 公平和非公平的实现区别
4. AQS提供的模板方法和加锁解锁流程
public final void acquire(int arg) {
if (!tryAcquire(arg) && //交给子类
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 加入队列和
selfInterrupt();
}
addWaiter cas的方式加入队列尾部 中间的enq包括自旋初始化head tail并确保插入
acquireQueued 自旋尝试前置节点是否是head并获取锁 否则shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt()
shouldParkAfterFailedAcquire
5. 共享锁、可中断锁、可控加锁时长锁
6. ReentrantLock怎么实现的 可重入的实现
7. ReentrantLock Api和基本用法
8. ReentrantReadWriteLock的实现逻辑 高16位记录读 低16位记录写
9. ReentrantReadWriteLock 读写锁加锁、释放锁流程
10. Object wait和notify/notifyAll用法 需要结合synchronized 翻书找出基本用法 看下原理
11. Condition的wait和notify/notifyAll用法 及源码 链表是单向的
12. 以上两者的区别 怎么实现生产者消费者
13. LockSupport park进入waiting状态 unPark synchronized进入blocked
14. Synchronized的应用场景 理解
15. Synchronized的实现原理 优化 偏向所-轻量级锁-重量级锁的锁升级过程
16. ConcurrentHashMap
17. CopyOnWriteArrayList
18. 线程池
COUNT_BITS 29 CAPACITY 29个1 RUNNING 高位111 SHUTDOWN 0 STOP高位001
TIDYING 高位 010 TERMINATED高位 011 通过和CAPACITY的运算计算线程数和状态
execute方法:
主流程:
1.workerCountOf(c) < corePoolSize--à addWorker(command, true) ->成功return
2.并列的if 因为并发等原因会存在add失败 (isRunning(c) && workQueue.offer(command)),内部再次检测运行状态 检测通过addWorker(null, false) 注意参数 不通过reject
3.elseif addWorker(command, false) 失败进入reject
addWorker流程:
双自旋,外层主要是获取判断运行状态 内层主要是获取在运行数并cas加1(内层判断运行状态 有变则跳出到外层)
包装成worker,通过factory创建线程,worker入HashSet
Worker的runWorker(Worker w) while(task或者队列获取task)->task.run
没有task进入processWorkerExit
processWorkerExit 从HashSet移除 判断是否应该结束 否->addWorker(null, false);
shutdown()方法:
mainLock加锁,checkShutdownAccess 遍历workers—check advanceRunState修改状态 interruptIdleWorkers中断workers的线程 onShutdown 空方法 最后tryTerminate
shutDownNow方法:
advanceRunState(STOP);状态修改为STOP drainQueue 移除队列中的任务
线程数配置:
Cpu密集 线程数=cup核心数
Io密集 线程数=2cpu核心数
Nthreads=Ncpu*Ucpu*(1+w/c) w:等待时间 c:计算时间 Ucpu:使用率0~1
Ncpu/(1-阻塞系数)
19. ConcurrentLinkedQueue
单向链表,但是有指针指向尾节点
offer主要是利用UNSAFE类进行队列的插入 poll
尾节点延迟更新 叫做HOPS 为了减少cas去更新tail
20. CountDownLatch、CyclicBarrier
两个主方法:await countdown
CountDownLatch:
CyclicBarrier:基于condition 当wait到一定程度 notifyAll
21. Semaphore、 Exchanger
Semaphore 可支持公平和非公平
1. acquire:利用AQS的acquireSharedInterruptibly
2. release 利用AQS releaseShared
Exchanger 线程数据交换
exchange:
22. ThreadLocal
Get:getMap-每个线程都有一个ThreadLocalMap 获取不到就setInitialValue 其中initialValue默认的是null 再次获取 获取不到创建createMap
Set:getMap createMap
ThreadLocalMap:key为弱引用 开放地址法处理hash冲突(定数:斐波那契数列) hashMap为分离链表法
弱引用的内存泄露 是因为在用线程池的时候线程不会回收,ThreadLocalMap也不会回收,map中的key是弱引用被回收。 已有优化:get set中会清理掉脏数据
23. 死锁
产生的必要条件:互斥、请求和保持请求、不可剥夺、循环等待
避免:单锁、tryLock。
检测:Jstack JConsole