解决伪共享问题的一种方法是通过填充(Padding)来确保共享的变量独立存储于不同的缓存行中 。填充的思想是在变量之间插入一些无关的数据,使它们分布到不同的缓存行,从而避免多个变量共享同一个缓存行 。Fork/Join框架Fork/Join框架是Java7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架 。
在Java中,可以使用@Contended注解来避免伪共享 。这个注解可以在字段上使用,它会在字段的前后插入填充,使得字段单独占据一个缓存行 。
Fork/Join框架需要理解两个点,「分而治之」和「工作窃取」 。
分而治之
文章插图
图片
工作窃取
文章插图
图片
一般就是指做得快的线程(盗窃线程)抢慢的线程的任务来做,同时为了减少锁竞争 , 通常使用双端队列 , 即快线程和慢线程各在一端 。ThreadLocal原理ThreadLocal的内存结构图:
文章插图
图片
- Thread线程类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals , 即每个线程都有一个属于自己的ThreadLocalMap 。
- ThreadLocalMap内部维护着Entry数组 , 每个Entry代表一个完整的对象,key是ThreadLocal本身,value是ThreadLocal的泛型值 。
- 并发多线程场景下,每个线程Thread,在往ThreadLocal里设置值的时候,都是往自己的ThreadLocalMap里存,读也是以某个ThreadLocal作为引用 , 在自己的map里找对应的key,从而可以实现了线程隔离 。
内存泄露问题:指程序中动态分配的堆内存由于某种原因没有被释放或者无法释放,造成系统内存的浪费 , 导致程序运行速度减慢或者系统奔溃等严重后果 。内存泄露堆积将会导致内存溢出 。
ThreadLocal的内存泄露问题一般考虑和Entry对象有关,ThreadLocal::Entry被弱引用所修饰 。JVM会将弱引用修饰的对象在下次垃圾回收中清除掉 。这样就可以实现ThreadLocal的生命周期和线程的生命周期解绑 。但实际上并不是使用了弱引用就会发生内存泄露问题,考虑下面几个过程:
文章插图
图片
当ThreadLocal Ref被回收了,由于在Entry使用的是强引用 , 在Current Thread还存在的情况下就存在着到达Entry的引用链,无法清除掉ThreadLocal的内容,同时Entry的value也同样会被保留;也就是说就算使用了强引用仍然会出现内存泄露问题 。
文章插图
图片
当ThreadLocal Ref被回收了 , 由于在Entry使用的是弱引用,因此在下次垃圾回收的时候就会将ThreadLocal对象清除 , 这个时候Entry中的KEY=null 。但是由于ThreadLocalMap中任然存在Current Thread Ref这个强引用,因此Entry中value的值任然无法清除 。还是存在内存泄露的问题 。
AQS实现原理
AbstractQueuedSynchronizer(AQS)是Java中用于构建同步器的基础框架 。它提供了一个灵活的、可重用的同步器实现,可以用来构建各种同步工具 , 如ReentrantLock、Semaphore、CountDownLatch等 。AQS的核心思想是基于FIFO等待队列,通过状态(state)来管理线程的同步 。
核心原理:
- State(状态): AQS 的同步状态是一个整数,表示被同步的资源的状态 。不同的同步器会使用不同的方式来表示状态的含义,例如,ReentrantLock 使用 state 表示持有锁的线程的数量,Semaphore 使用 state 表示可用的许可数量等 。
- FIFO 等待队列: AQS 使用一个FIFO的等待队列来管理获取同步资源失败的线程 。每个节点(Node)表示一个等待线程,节点中保存了等待状态、前驱节点、后继节点等信息 。当一个线程尝试获取锁但失败时,它会被包装成一个节点并加入到等待队列中 。
推荐阅读
- 深入浅出SSH隧道穿透
- 百度推荐排序技术的思考与实践
- SEO内容页优化及文章页优化,提升网站流量与用户体验的关键技巧
- 无视汪小菲官宣新恋情秀恩爱,大S复出拍广告,身形暴瘦与以往判若两人
- 这5部电影,让你真正感受女性的魅力与坚韧
- 金卡戴珊与四姊妹,全凭她们能干的妈妈,目前红遍整个美国
- 双减政策出台的利与弊,双减政策是由国家出台的吗
- 陈龙与章龄之像普通夫妻一样,也有着烟火气,妻子发文称没嫁错人
- 王菲西藏朝拜引热议,网友质疑其虔诚度与慈善行为
- 曾昭怡晒视频:与干妈何超琼开心合影,和甘比一起比耶拍照!