程序员的护城河-并发编程

简介: 程序员的护城河-并发编程

前言


世间不如意十之八九。如果没办法一次到位,就分阶段实现吧。


并发编程详解


感慨


历时一个月,从一个只知道背八股的选手,到了对JAVA中常见的并发编程知识熟悉,这是一个蜕变,其实并发编程并不是一个单单的部分,当完整的学习完一个体系,就会发现,很多框架、中间件等都有并发编程的思想,比如Redis等,学会并发编程后也代表着真正的打开了走向高阶程序员的大门,这个过程注定是艰辛的,但是收获确实巨大的!!!


为此,奔着笔记和分享的原则,将整个学习体系的思考和研读整理成博客,供他人参考和指正,在此也希望能获得大家宝贵的意见,一起学习,共同进步。


进程与线程


概述进程与线程之间的关系以及简单测试多线程的好处


👉👉👉 剑指JUC原理-1.进程与线程-CSDN博客


线程


主要概述创建线程的方式以及线程运行的原理


👉👉👉 剑指JUC原理-2.线程-CSDN博客


线程常用方法及状态


本章节主要概述了JUC常见的API 以及 几种线程状态 和 其资源占用情况


👉👉👉 剑指JUC原理-3.线程常用方法及状态-CSDN博客


共享资源和线程安全性


本章节详细的介绍了线程安全性,列举多个案例来论述 共享资源读写问题、是否安全


👉👉👉 剑指JUC原理-4.共享资源和线程安全性-CSDN博客


synchronized底层原理


本章节尽可能的去讲解了synchronized 的发展流程,包括Monitor、重量级锁、轻量级锁、偏向锁、自旋优化等等。


👉👉👉 剑指JUC原理-5.synchronized底层原理-CSDN博客


wait notify


本章节主要讲解的是 关于 同步实现 和 异步实现的原理,同步实现通过观察join源码发现其实是一种保护性暂停的策略,而异步实现其实有点像消息队列的感觉,本质上就是 不管生产者传过来过,消费者不会立马消费掉,这里其实使用阻塞队列的思想就可以实现。


👉👉👉 剑指JUC原理-6.wait notify-CSDN博客


线程状态与ReentrantLock


本章节其实主要介绍了 死锁问题的发生以及如何的排查死锁,具体的可以使用jsp + jstack && top + top H + jstack && jconsloe 来排查问题,同时介绍了与synchronized 对比的一种可重入锁 ReentrantLock 的特点。


👉👉👉 剑指JUC原理-7.线程状态与ReentrantLock-CSDN博客


Java内存模型


本章节主要介绍了 Java内存模型 中的 原子性 可见性 有序性的观点,并着重的介绍了如 volatile 内存屏障的相关原理,并且以 高并发下的单例模式举例来论证 三大特性。


👉👉👉 剑指JUC原理-8.Java内存模型-CSDN博客


Java无锁模型


本章节主要介绍了 无锁模型cas具体是什么原理,以及基于cas的原子类,最终剖析了其最底层unsafe的实现,其底层是通过获取偏移量然后再进行比较。


👉👉👉 剑指JUC原理-9.Java无锁模型-CSDN博客


并发编程大师的原子累加器底层优化原理(与人类的优秀灵魂对话)


本章节主要介绍了 原子累加器 LongAdder的底层实现,其性能较好,本质上适合高并发场景的累加,分为有竞争 和 无竞争,有竞争做的优化是 创建一个累加单元数组,并发的去累加,并且针对各种逻辑进行了详细的校验。


但是有利也有弊,其性能非常好,适合高并发场景,但是精准度存在一定的问题


在这里只着重介绍一下 longadder 的 sum操作。


当我们最终获取计数器值时,我们可以使用LongAdder.longValue()方法,其内部就是使用sum方法来汇总数据的。


java.util.concurrent.atomic.LongAdder.sum():

public long sum() {
    Cell[] as = cells; Cell a;
    long sum = base;
    if (as != null) {
        for (int i = 0; i < as.length; ++i) {
            if ((a = as[i]) != null)
                sum += a.value;
        }
    }
    return sum;
}

实现很简单,遍历cells数组中的值,然后累加.


看上去LongAdder的性能全面超越了AtomicLong,而且阿里巴巴开发手册也提及到 推荐使用 LongAdder 对象,比 AtomicLong 性能更好(减少乐观 锁的重试次数),但是我们真的就可以舍弃掉LongAdder了吗?


当然不是,我们需要看场景来使用,如果是并发不太高的系统,使用AtomicLong可能会更好一些,而且内存需求也会小一些。


我们看过sum()方法后可以知道LongAdder在统计的时候如果有并发更新,可能导致统计的数据有误差。


而在高并发统计计数的场景下,才更适合使用LongAdder。


总结


LongAdder中最核心的思想就是利用空间来换时间,将热点value分散成一个Cell列表来承接并发的CAS,以此来提升性能。


LongAdder的原理及实现都很简单,但其设计的思想值得我们品味和学习。


👉👉👉 剑指JUC原理-10.并发编程大师的原子累加器底层优化原理(与人类的优秀灵魂对话)-CSDN博客


不可变设计


本章节主要介绍了 之所以会出现线程安全问题的原因,并结合String 中不可变设计 final 引出享元模式

👉👉👉 剑指JUC原理-11.不可变设计-CSDN博客


手写简易版线程池思路


本章节主要介绍了 一个简易版本线程池的设计思路,其本质其实就是阻塞队列,并且讲 核心线程的run方法重写,使其能够不停地复用,并且在复用的过程中还可以选择那种复用策略,是死等还是超时等待,最后再设计拒绝策略即可。


👉👉👉 剑指JUC原理-12.手写简易版线程池思路-CSDN博客


线程池


本章节主要介绍了真正的线程池,讲解了其几个核心参数 以及 FutureTask实现 和 Tomcat对线程池改造的思路。


👉👉👉 剑指JUC原理-13.线程池-CSDN博客


ReentrantLock原理


本章节首先介绍了AQS指导思想,然后又深入ReentrantLock源码去探究 公平非公平、可重入、可打断、await、signal等原理。


👉👉👉 剑指JUC原理-14.ReentrantLock原理-CSDN博客


读写锁


本章节介绍了基于ReentrantLock得读写锁,其实本质上换汤不换药,虽然分为了读写,但是只需要合理的控制state的高16位 和 低16位即可,同时在等待队列中做好新的标记,新增了shared 和 Ex标记,如果读获取到锁,还需要看看后面还有没有对应shared状态的一并解锁。


👉👉👉 剑指JUC原理-16.读写锁-CSDN博客


ThreadLocal


本章节首先介绍了ThreadLocal的基本使用场景,其次深入对应常用方法的源码,最后 针对可能存在内存泄漏的情况 以及 出现hash冲突时是怎么实现的(使用了线性探测法


👉👉👉 剑指JUC原理-15.ThreadLocal-CSDN博客


CompletableFuture


本章节主要介绍了Future的加强版 CompletableFuture 的使用,其中调用链逻辑有 后一步需要前一步、需要不需要返回值、将所有的结果整合起来等,合理的使用能够极大的提高使用效率,但是 如果使用的话,最好在get处设置超时时间,并配置 complete 返回默认值。


👉👉👉 剑指JUC原理-17.CompletableFuture-CSDN博客


同步协作


本章节主要介绍了信号量同步方面原理,其实还是基于ReentrantLock的思路进行设计,所以可见AQS思想有多么的重要了,其次还介绍了 线程协调。


👉👉👉 剑指JUC原理-18.同步协作-CSDN博客


线程安全集合


本章节主要介绍了常见的第三代线程安全集合,当然得需要先学会其前置知识HashMap,详细介绍了HashMap在多线程的情况下出现的问题,以及ConcurrentHashMap 在不同的版本做的改进,然后还有阻塞队列 以及 CopyOnWrite思想,当然最本质的还是 一致性 和 并发性的问题,这个最直接的体现就是数据库的MVCC 和 LongAddar。


👉👉👉 如果面试也能这样说HashMap,那么就不会有那么多遗憾!-CSDN博客


👉👉👉 剑指JUC原理-19.线程安全集合-CSDN博客


并发编程实践


相信通过前面铺垫的20章,对于并发编程在原理层次应该是非常熟悉的了,在我的认知里,如果学习了原理性的知识而不去实战,那么这样学习是完全没有意义的,所以为了巩固我之所学,一个集成了网络上众多并发实战应用性的专题应运而生,详细的介绍了并发编程到底可以做什么,到底能够解决那些实际的问题,以及其局限性的思考,这些在我眼里是非常重要的,也就是知行合一的过程!


👉👉👉 剑指JUC原理-20.并发编程实践-CSDN博客


总结


学习JUC是完善整个后端体系必不可少的一环,因为很多Java后端的中间件或者框架其本身内部大量的涉及到了JUC的部分,并且也可以在阅读JUC源码的过程中明白思想,其实思想都是互通的,例如ReentrantLock的原理本质上和Redisson 的原理是类似的,那么就可以迅速过度到分布式锁的使用中。


总的来说,当完整的学习完JUC的部分,也相当于内功更胜一步,这比我当初做完谷粒商城的感觉还好,感觉作为程序员的核心素养更强了,感触良多,耗时一个月,其所体现的绝不是这二十一篇文章这么简单,更多的是传递思想,传递动力,我行你也行的态度!!!


目录
相关文章
|
6月前
|
资源调度 算法 Java
Java并发编程的艺术:并发编程的挑战
Java并发编程的艺术:并发编程的挑战
42 0
|
6月前
|
存储 搜索推荐 程序员
SnippetsLab:程序员的秘密武器
SnippetsLab:程序员的秘密武器
204 0
|
安全 Java 调度
【并发编程技术】「原理和发展史」名贯古今的技术领域—并发编程,早就新的技术时代
【并发编程技术】「原理和发展史」名贯古今的技术领域—并发编程,早就新的技术时代
163 0
|
缓存 负载均衡 算法
一文带你领略并发编程的内功心法
本篇文章我们来探讨一下并发设计模型。 可以使用不同的并发模型来实现并发系统,并发模型说的是系统中的线程如何协作完成并发任务。不同的并发模型以不同的方式拆分任务,线程可以以不同的方式进行通信和协作。
95 0
一文带你领略并发编程的内功心法
|
分布式计算 算法 Java
java并发编程的艺术(1)并发编程的挑战
java并发编程的艺术(1)并发编程的挑战
118 0
|
存储 Java 程序员
程序员,别再迷恋多线程工作了
我刚刚尝试了一下,一边用 iPad 看“Java 极客技术”自制的 SpringBoot 视频(1.2X 倍速),一边在 iMac 上回复博客上读者的留言。过了一会,视频上讲了什么,我完全没有印象了;而回复的内容也写得乱七八糟。
|
存储 Java 程序员
@程序员,别再迷恋多线程工作了
@程序员,别再迷恋多线程工作了
126 0
|
分布式计算 算法 NoSQL
如果说程序员的硬通货是技术,那么软技能是什么?
程序员往往一心扑在编程技术上面,学习编程语言,算法,网络,自己子领域相关的知识等等。这非常正确,也是作为coder的核心竞争力所在,姑且称之为“硬技能”吧。 对于有一个程序员来说除了日常码代码之外,其实也需要很多编程之外的软件能,非专业上面的技能可以更好的展现你的情商,与人合作的能力等。
|
程序员

相关实验场景

更多