我所知道并发编程之聊聊并发、多线程、多进程、多线程快?、并发四个阶段

本篇目录

  • 你真的了解并发吗?为什么要使用并发?
  • 多线程和并发
  • 多线程和多进程
  • 多线程一定快吗
  • 学习并发的四个阶段

一、你真的了解并发吗?为什么要使用并发?


我们有没有见过并发的场景呢?

其实并发是无处不在的,比如,淘宝的双十一就是一个非常高的并发量,就是很多人同时去访问一个网站,而这个网站却能够支撑大量的并发访问,这就是一个并发的场景.

细致的说,web容器、数据库服务器,等等各类的服务器软件,都是支持并发的,那么并发的性能就直接的影响到软件的性能

所以并发编程在整个并发应用的场景下是非常关键的,除了我们刚刚说的各种服务应用之外,那么还有没有其他的地方用到并发呢?

其实也是非常多的刚刚说的是服务端那,我们说个客户端eclipse就是一个客户端应用它也有大量的并发场景

比如说我们在编辑代码的时候,它可以做很多的事情:可以同时运行一个web服务、它还在进行编译、甚至可以说底层的垃圾回收等等

也就是说,并发场景在我们的生活中是无时无刻不在发生的,

那么并发有哪些优点呢?现在硬件越来越便宜,那么我们就可以通过增加硬件的方式,来提高一个性能。

比如说可以使用多核CPU,使用并发可以发挥出多核处理器的强大的能力,当然了也不仅仅是多核,我们可以直接说多处理器,能够发挥多个处理器的强大的运算能力,除了发挥多核处理器的强大能力之外,能够让我们的建模更加的简单,就是所谓的建模的简单性。

所以我们要学习并发编程。

二、多线程和并发


多线程和并发之间到底有什么关联呢?它们之间又有哪些差异呢?我们就来探讨一下。

首先说一下什么是多线程,其实之前已经给大家讲了一个非常简单的例子了

假如这是我们的一个应用,假如我们在这里面写代码

我们知道,程序是一行一行的往下执行的,在Java虚拟机运行时内存区域中,有一块叫做PC寄存器,类似于代码编辑器中的linenumber,指示的是行号,Java虚拟机就跟着行号一行一行的往下执行。

肯定不会说从执行完int a = 10; 之后,接着先执行int c = a + b; 然后再回过头去执行int b = 20; 这是绝对不可能的,这就是单个线程在执行。

就是说,这里面的代码是一行一行的往下去执行的,不会乱序去执行,

我们知道在运行一个非常复杂的代码的过程中,Java的内存管理,我们并不需要手动的去管理内存,Java提供了自动内存管理机制,内存的申请和释放都是由Java虚拟机来自己完成的。

那么,在进行垃圾回收的过程中,就需要调用垃圾收集器(GC),那么你这个程序在运行的过程中,垃圾收集器也是在工作的。

我们发现我们并不知道垃圾收集器在工作,但是垃圾收集器却是已经在工作了,怎么回事呢?

其实有另外一个线程在执行垃圾收集器,就是专门的垃圾收集器线程,它里面也有一行一行的垃圾收集代码

那么,在我们程序运行的过程中,这些代码会自动的悄悄的往下去执行。

Java虚拟机中的内存区域,主要分为两大区域,一个是线程共享区,一个是线程独占区,我们知道,堆和方法区是被线程所共享的区域,就是所有的线程共享这块区域,除了这两块区域以外,还有程序计数器

这块区域是被线程所独享的,也就是说每个线程都有这么一块区域,因此,这两个各自都有各自的程序计数器

这两个之间是互不干扰的,也就是相当于有两段代码在同时的进行,这就是多线程

然后我们接着说并发的问题,多线程和并发到底有什么关系呢?

并发就是并行的执行,是不是跟多线程非常的类似呀,那么多线程是不是就是并发呢?

其实不是,从广义上来说,我们可能就认为多线程就是并发,但是,实际上多线程不是并发,我们可以这么去想。

我们知道源码会被编译成字节码,而我们Java虚拟机执行的就是字节码指令,那么它在最终执行过程中是由CPU执行的

image.png

假设有一个一个炉子用来考烧饼的,这些是炉子上面放的烧饼

image.png

这个炉子的下面,有一个火炉

image.png

如果当火转到对应的这个火炉上面的烧饼才开始烤,假设这个烧饼是我们的线程,而下面的这个火炉是我们的CPU

image.png

当炉子在转的非常快的时候,我们说,任务的切换线程之间的切换时间就会非常的短,那么我们就会看起来像是在同时执行,但是其实并不是在同时执行,它是在不停的切换的,就类似于图片切换的频率非常高的时候就成了动画或成了视频

这个原理其实也类似于我们的灯泡,灯泡其实也是在不停的闪的,我们看到灯泡一直亮,就是因为它闪的频率非常的高,这就是多线程。

多线程其实并不是多个线程一起执行而是线程之间因为切换的速度非常的快,所以,我们看起来像不间断的执行

那么,并行又是什么呢?并行就不一样了,并行表示的是多个任务同时执行

就是说,这么多的烧饼在一块烤,那怎么做到的?有多个炉子就可以做到了。每个烧饼下面有一个炉子,这样就能做到一块烤了,这就是所谓的并行。

那么,并发和多线程之间其实通过这个例子就可以看的非常清楚了,多线程并不一定是并发,如果是并发执行,那么肯定是多个线程在一块执行,当然也未必,多个进程也是并发执行。

这就是多线程和并发之间的关系。

三、多线程和多进程的关系


什么是进程?简单来讲就是运行中的程序,那么何为运行中的程序呢?我们如何来看看进程呢?

操作系统都是多进程的。我们通过任务管理器就可以看到操作系统中当前运行的很多的进程

image.png

进程和线程之间到底有什么关联呢?

首先进程是资源分配的基本单位,第二个进程中包含多个线程,线程可以共享进程的资源。

我们可以这么理解,就是说进程是操作系统级别的,一个操作系统运行了多个进程,每一个进程里面有包含着多个线程,我们可以通过下图这个地方来看

image.png

这里面有一个CPU的统计信息,此处有一个进程数是137,就是运行了137个进程,线程有1720个

显然线程的数量远远大于进程的数量,也就是说,一个进程里面会有多个线程。

我们的eclipse软件就是一个进程,我们看一个进程中到底包含了多少个线程呢?我们之前也通过jconsole监控工具

image.png

为什么处理器调度的基本单位是线程而不是进程?我们说,进程是资源分配的基本单位,在进行进程之间的切换的过程中,它会浪费更多的资源,然而线程可以说是轻量级的进程,所以CPU的调度的基本单位是线程

这就是线程和进程之间的联系与区别

image.png

四、多线程一定块吗?


多线程执行一定会快吗?

我们大家可能都知道在很多的下载的网站上,都会提多线程下载,那么我们也同样的发现,使用多线程下载远比单线程下载要快的多。这样可能大家都会认为多线程一定比单线程快,其实并不一定

我们来举个例子,还是拿之前烤烧饼的例子来说,下面只有一个炉火,上面在不停的转,这样烤一定会快吗?

image.png

咱大家想一下如果我们不这样做,我们不让它转,就让它烤这一个,等它烤熟了之后,我们再拿另外一个烤

image.png

那么我们想一下,是之前的全部放上去让炉子转起来烤,烤的快呢?还是我一个一个放上去烤,烤的快呢?

其实是非常明显的,如果选在转的话,在转的过程中,每个烧饼(线程)切换的过程中是有空隙的

image.png

线程任务之间在进行切换,也就是说,烧饼在进行切换的过程中,它是要浪费我们的资源的,也就是要浪费我们的能量的,因此,其实是远远不如一个一个的执行反而更快一些

回过头我们再来解释刚才提到的关于迅雷下载,就是说多线程下载的问题,多线程下载为什么一定能够提高,也并非一定能够提高下载的速度?

按理绝大部分情况下是可以的,为什么呢?因为,我们说做一个文件服务器的话,允许用户去下载那么,它肯定不会说你这个链接过来了,我就会毫无保留的一下子把我的带宽全部给你让你去下载

我肯定是为每一个链接分配一定的带宽,比如说,你这一个连接进来,我就给你这个响应最高200k不能再多了,那么也就是说你这一个链接进来,它的峰值下载速度也就是200k,那么它是一个链接级别的。

那么,我可以把要下载的一个文件分成多个,切分成多个,我用多个线程一块去下载,那么,每一个链接200k,假设有三个链接,那么,加起来就是一共有600k的下载速度。

那么等我把切分的每一小块文件都下载完了之后,我在把这些小文件合并起来就可以了,这样下载的速度就会变的很快,也就是说多线程下载并不是多线程提高了速度,不是多线程的性能提高了。

而是由于外部服务器对资源的限制,所导致的一个问题那么多个链接就突破了这个远程服务器的限制,也就导致了性能的提高。

也就是说,虽然看着下载速度快了,并不是多线程的性能提高了,而是由于远程服务器的问题

五、学习并发的四个阶段


第一阶段:熟悉掌握API,能够完成并发编程

熟练掌握并发相关的API,能够完成基本的并发编程

也就是我们所熟悉的继承Thread也好,实现Rannable接口也好,使用各种的锁,根号中期,注册队列等等

你要熟练掌握这些和并发相关的API,这是第一个阶,这个阶段目标是:how(怎么做)

第二阶段:熟读API源码,掌握原理

我们会用这些API还不行,我们要掌握这些API实现的原理,了解了这些原理之后对我们来说

无论是深入理解并发也好或者说以后我们的编程也好都是有非常大的帮助的,这个阶段的目标是:what(what)

第三阶段:理解Java虚拟机的内存模型

Java的运行是基于JVM的,那么JVM**是如何解读多线程的呢?如何解读我们的并发代码呢?

**这就需要我们深入理解Java虚拟机的内存模型,以及Java虚拟机执行多线程的执行引擎等等

就是关于虚拟机相关的对线程的一些支持,这就深入到了Java虚拟机的层次,这就是第三个阶段

第四阶段:操作系统对并发的支持

Java虚拟机是运行在操作系统上的,第四个阶段就是操作系统对并发的支持有哪些

参考资料


龙果学院:并发编程原理与实战(叶子猿老师)

你可能感兴趣的