ThreadLocal
每个 Thread 拥有一个 ThreadLocalMap,它存储了该线程使用的所有的 ThreadLocal 对象和对应的值。
线程池与 ThreadLocal 一起用时有什么问题?
内存泄漏、
脏数据:线程被不同的任务重复利用,如果没有及时清除 ThreadLocal 存储的数据,下一个任务就可能访问到上一个任务设置的数据。
AQS
AQS只是一个框架,具体的资源的获取/释放由自定义同步器去实现。
AQS最核心的是 volatile int state(资源)和一个 FIFO 等待队列(线程被堵塞就在这排队)。
AQS的两种资源共享方式
独占:Exclusive,只有一个线程可执行
共享:Share,多个线程可同时执行
ReentrantLock
ReentrantLock是独占资源。state 初始化为0,表示未锁定,A线程 lock() 时,会调用 tryAcquire() 独占锁并让 state + 1。此后,其他线程再 tryAcquire() 时就会失败,直到A线程 unlock() 到 state = 0为止。其他线程才有机会获得锁,当然释放锁之前,A线程可以重复获取此锁,这就是可重复的概念。但是获取多少次就需要释放多少次。
ConcurrentHashMap
在 JDK1.7 中采用 Segment + HashEntry + 链表实现。一个 Segment 包含一个 HashEntry 数组,每个 HashEntry 数组的结构是数组 + 链表。
get() 操作
与 HashMap 的 get() 操作类似,只是 ConcurrentHashMap 需要先经过 hash 定位到对应的 Segment,之后与 HashMap 类似。
put() 操作
1、首先会根据 hash 计算出 Segment 的位置。
2、通过继承ReentrantLock的tryLock()方法尝试去获取锁,如果没有成功则继续尝试,如果对该Segment加锁成功则与 HashMap 的put操作类似。
3、释放 Segment 锁。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1216271933@qq.com