目录

ThasBlog

学无止境

标签: 源码 (3)

Java AQS 有更新!

AQS AbstractQueuedSynchronizer, 队列同步器, 支持队列等待。 继承自 AbstractOwnableSynchronizer, 不带队列的同步器, 只能有一个线程同步, 其他线程忽略。 AQS 使用 state 和 一个 FIFO 队列来进行线程同步。 state 表示申请资源的状态, 默认 0, 若已被占用则小于 0. AQS 不关注申请和释放资源的方式, 只提供了操作 state 的方法。 在并发申请资源过程, AQS 维护各个线程获取资源的原则, 如不满足获取资源的条件, 则先将它们放入等待队列, 等待资源可以被申请了, 再唤醒等待队列中的线程。 申请和释放资源的方法需要锁自己实现: 1// 尝试申请资源 2boolean tryAcquire(int arg) 3// 尝试释放资源 4boolean tryRelease(int arg) 5// 资源是否被独占 6boolean isHeldExclusively() 7// 尝试以共享模式申请资源 8int tryAcquireShared(int arg) 9// 尝试以共....

Java8 ConcurrentHashMap 有更新!

ConcurrentHashMap 是 HashMap 的线程安全版本, 使用了 CAS, volatile 和 synchronize 技术。 初始化时使用 volatile 修饰的 sizeCtl 作为互斥条件, 如果有其他线程正在操作则 Thread.yeild(). 在插入元素时, 如果元素不存在, 则使用 CAS, 在插入新元素时, 如果元素不存在才能插入成功, 否则失败重试, 如果是 MOVED 状态, 则先辅助扩容, 完成后再尝试插入。 如果元素存在, 需要进行修改或者 Hash 冲突, 则加 synchronize 锁进行处理(因为情况比较复杂, 可能是链表, 可能还需要树化), synchronize 修饰 bin 上的第一个元素 元素数量修改时, 并发高的情况容易 CAS 失败, 引入 counterCells 数组减小 CAS 失败的概率 数组扩容时, 分段迁移, 每段最少 16, 迁移前 CAS 设置 transferIndex, 设置成功则得到该小段的迁移的权利。 迁移时, 如果该 bin 上有值, 则 synchronize 锁住, 如果无值, 则 CAS....

Java8 HashMap 有更新!

HashMap Map 意思是映射, 从 key 映射到 value. HashMap 就是基于 hash 的 key 来实现映射关系。 数组是在连续的固定大小的内存空间上顺序且紧凑地存储元素的集合。 数组支持随机读写, 其本质原因就是紧凑存储。 通过数组头部位置 + 索引就可以直接获得指定元素的地址, 对该地址直接进行读写。 但紧凑存储同时带来另一弊端, 为了保证数组元素紧凑, 每次在数组中间增删元素时都需要挪动数组元素以保证数组中间没有空缺。 数组索引 = 元素在数组中的位置, 数组索引是顺序的且永远不会重复。 Hash 表继承了数组的优点, 支持随机读写, 又不需要(频繁)挪动元素。 牺牲了少量额外内存空间和散列计算开销。 Hash 索引 = 散列函数(元素), Hash 索引不是顺序的, 只与元素本身相关, 但是是可能重复的。 当 Hash 索引重复时, 一个索引会对应多个元素, 这就是 Hash 碰撞, 这时 Hash 表随机读写的优势就会降低。 适当的增加 Hash 表分配的内存空间可以减少 Hash 碰撞几率, 所以 Hash 表通常会有额外的未利用内存空间。 链地址法(....