【并发编程技术】「原理和发展史」名贯古今的技术领域—并发编程,早就新的技术时代

简介: 【并发编程技术】「原理和发展史」名贯古今的技术领域—并发编程,早就新的技术时代

并发编程历史观


并发编程(Concurrency Programming),从字面意思来看,自然让人联想到两个或多个的意思。并发编程的出现是计算机硬件,操作系统进步的结果,也是计算机科学追求更快速度,更高效率解决问题的结果。



并发出现之前


在并发出现之前,程序的执行自然就都是串行了。那时计算机CPU都是单核的,内存也非常小。需要利用计算机解决的问题也远没有现在这样复杂。因此将程序串行化自然能够解决很多问题。


随着计算机软件和硬件的发展,不仅一台计算机可以有多个CPU,一个CPU还可以有多核。内存变得越来越大,速度也变得越来越快了。为了充分利用这些资源,同时为了提高计算效率和应对更大的计算量,自然而然出现了并发编程技术。



并发的基本概念


并发和并行


并发和并行,虽然只有一字之差,事实上这两个概念有很大的不同。


  • 并发是多个线程做同一件事情:
  • 这些进程可能一点关系也没有,举个例子,求N个数之和,我们可以将这N个数分成M分,用M个线程去分别求和,最后再由一个线程合并求和,这就是并发。
  • 并行是多个进程做不同的事情:
  • 一个程序做的事情是求N个数之和,不管这个程序是一个线程完成还是多个线程完成。
  • 另一个程序做的事情是求N个数的乘积,也不管这个程序是一个线程完成还是多个线程完成。
  • 这两个线程在各自的内存区域共同受一个CPU调度,而且这两个程序还是同时进行。那这就是并行。


总结来说,并发是彼此之间有联系,可以共享数据,并行是彼此之间没有多少联系,做着不同的事情不会共享数据。



并发编程


由并发牵扯到的一个最重要的概念就是线程(Thread),并发的手段就是多线程,因此并发编程也可以叫做多线程编程,如果没有多线程的编程绝对不能叫做并发编程。


并发编程的执行单元


并发编程的执行单元,那线程又是什么?线程可以理解为小粒度的进程,和进程的区别在于线程之间共享内存,进程之间独立内存。


串行和并行


串行


串行的反义词是并行,串行可以理解为一次只做一个事情,从微观层面来看,CPU的指令执行必定都是串行的,一个时钟周期内,单个CPU的单个核内不可能同时执行两条指令。


并行


并行的话上面说过,是多个进程做不同的事情,从微观上来看,一个多核CPU或者多个CPU在同一个时钟周期内,执行不同的指令可以认为是并行。


单核和多核


随着计算机硬件的发展,逐渐出现了多核甚至多个CPU(宏观上可以把多核和多CPU等同),这样并发编程就自然而然出现了。


事实上,这种说明严格来说,是不符合历史的。不能说多核就一定是并发,单核就一定只能是串行。单核也可以并发,多核自然绝对可以串行。


多CPU(或者说多核)出现之前,是有并发的。只不过这时候的并发从指令的微观层面来看,它是串行化的,一个CPU时钟周期内,一定只有一个线程在运行。


因此,这个时候,多线程编程的性能和效率不一定比串行编程要高。当然,并行比串行自然效率要高。


举个例子,某个程序是CPU密集计算,某个时刻正在CPU计算,另一个 程序是IO密集的,同一时刻可以调度它去进行IO计算而不影响CPU密集计算的程序,这样自然就提高了效率。


单核可以并发,也可以并行,多核的场景下进行并发编程比单核效率要高很多。这里有一个阿姆达尔定律来说明这个事情。关于阿姆达尔定律。




并发编程的影响


很显然,并发编程带来的最大影响是提高了计算效率,充分利用了计算资源(并行也是为了充分利用计算资源)。但同时并发编程也带来了一个巨大的影响,那就是使得编写并发程序变得困难起来,编写正确的程序就已经比较难了,编写正确的并行程序就是难上加难。


编写并发程序为什么更加困难?原因在于并发程序需要处理线程调度,数据共享问题。因为数据共享带来的线程安全问题。


同时,多线程就意味着需要额外的调度逻辑,这多出来的调度会带来线程的上下文切换等损耗。因此多线程不是高性能的良方。恰当地使用多线程,小心翼翼地编写并发程序才是对策。


有时候,我们甚至不能忽略线程切换带来的性能下降,更加不能容忍多线程带来的线程安全导致错误的计算结果问题。



提高计算效率吗


多线程不是高性能的最好办法。可以这样说,多线程的目的在于充分利用计算机硬件资源和软件资源,使其不断处于忙碌状态从而提高生产效率。而高性能的解决办法有时候需要从更加宏观的地方入手。



分布式架构


目前,互联网里分布式架构应该比较流行。因为解决高并发,大流量问题很多时候就是分布式。现在比较流行的微服务也可以理解为更小粒度的SOA。计算机科学里还是现实生活中,我们解决大问题的思路就是拆分。将大问题拆分成小问题,将大模块拆分成小模块。然后利用多实例,多服务来解决。因>此,从宏观层面来看,分布式和并发的思想上有某种契合。都是化大为小,各个击破。



协程


多线程必然带来线程切换的问题。线程切换就会消耗额外的计算资源。因此计算机科学里又有了一种协程的说法。可以这样认为,线程是小粒度的进程,而协程可以理解为小粒度的线程。协程不需要上下文切换,在方法调用里调用其他的方法不需要切换资源。这里的关键在于利用了CPU的中断。因此避>免了线程切换带来的资源消耗。未来,Java必将支持协程。而目前Python已经支持协程了。



Java并发编程的基本手段


实现Java多线程的手段以及基本用法(Thread,Runnable,Callable),static,final等对线程安全的意义



线程安全和线程通信问题


引出临界区,数据竞争以及线程通信模型,深入讲解线程通信的方法(分析ThreadLocal类)以及意义



原子性与可见性


因为多线程通信问题,可能引发原子性和可见性等问题,从Java语言层面讲解原子性和可见性



Java内存模型(JMM)

继续深入,理解JMM,从JMM角度深入理解synchronized和volatile



J.U.C概述

JDK并发工具包介绍,从该包的结构以及功能上做一个概述,为后面的分解铺垫思路



深入J.U.C中的锁

深入分析Java语言层面提供的锁机制以及实现原理,对比分析synchronized的异同和优劣



深入J.U.C中Executor框架

深入分析Java中线程池,比较分析4中线程池的异同以及用法


深入J.U.C中并发容器类

简单分析各个容器类的作用和用法,重点分析ConcurrentHashMap


深入J.U.C中原子类

简单分析各种原子类的用法以及作用,重点分析CAS操作的实现以及底层机制


深入J.U.C中并发工具类

简单分析各个工具类的用法以及作用,重点分析CountDownLatch和CyclicBarrier


并发编程总结

这个思路从简单到复杂,基本是按照并发编程学习的思路来的。当然,各个章节也很独立。可以作为单独的复习或学习参考。希望这个专题能给自己和他人带来知识上的梳理与巩固。






相关文章
|
5月前
|
Java 大数据 调度
书评 | 《深入理解高并发编程:JDK核心技术》
书评 | 《深入理解高并发编程:JDK核心技术》
91 0
|
5月前
|
安全 物联网 Java
未来交织:新兴技术的融合与革新深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第27天】 在数字化的浪潮中,创新技术如同星辰般璀璨,引领着时代的前行。本文聚焦于区块链、物联网(IoT)、虚拟现实(VR)等前沿科技,剖析它们的发展脉络,并探讨这些技术的交互融合与实际应用。通过深入分析,我们预见这些技术将如何重塑经济结构、改善人类生活,并引发社会层面的深刻变革。
|
5月前
|
资源调度 算法 Java
Java并发编程的艺术:并发编程的挑战
Java并发编程的艺术:并发编程的挑战
39 0
|
5月前
|
机器学习/深度学习 人工智能 自然语言处理
简述谈一谈人工智能
简述谈一谈人工智能
|
5月前
|
消息中间件 安全 Java
程序员的护城河-并发编程
程序员的护城河-并发编程
49 0
|
缓存 监控 安全
【并发技术系列】「并发编程」技术体系和并发模型的基础探究(夯实基础)
【并发技术系列】「并发编程」技术体系和并发模型的基础探究(夯实基础)
154 0
【并发技术系列】「并发编程」技术体系和并发模型的基础探究(夯实基础)
多线程编程核心技术-java多线程技能(1)(下)
多线程编程核心技术-java多线程技能(1)(下)
多线程编程核心技术-java多线程技能(1)(下)
|
分布式计算 算法 安全
史上最全的Java并发系列之并发编程的挑战
前言 文本已收录至我的GitHub仓库,欢迎Star:github.com/bin39232820… 种一棵树最好的时间是十年前,其次是现在
161 0
下一篇
无影云桌面