Java 并发编程解析 | 每个Java Developer都应该知道的关于并发编程的那点事?
苍穹之边,浩瀚之挚,眰恦之美; 悟心悟性,善始善终,惟善惟道! —— 朝槿《朝槿兮年说》
写在开头
在这个互联网应用乱象丛生的时代,应对复杂业务需求,如何开发和设计一个高效和稳定的应用程序,一直都是我们备受瞩目的关注点 。作为一名Java Developer,从接触 Java 开发到现在,相信大家对于并发编程这个概念都不陌生,你对 Java并发编程最直观的印象是什么呢?是各个大厂面试宝典宣扬的高频热词,还是在实际工作中,都有过实际工作场景必备高阶开发技术?关于并发编程的基础和原则都做到了然于胸了吗?接下来,我们一起总结和思考一下。
并发编程三要素
所谓并发编程是指在一台处理器上“同时”处理多个任务。并发是在同一实体上的多个事件。多个事件在同一时间间隔发生。——百度百科
对于时实际编程过程中,其实相当一大部分的任务都是可以通过顺序编程来解决,只是对于某些特殊的和特定的问题,并发编程会让我们对于应用程序的操作与控制可以变得十分方便甚至必要。很大程度上说,并发编程"具有可论证的确定性,但是实际上也具有不可确定性“,正是因为如此,并发编程令人最困惑的一个原因:使用并发时需要解决的问题有多个,而实现并发的方式也有多种,并且两者之间没有十分明显的映射关系。从并发编程帮助我们解决问题来说,主要是应用程序“运行速度”和“设计可管理性”两个方面。
从而我们知道,并发编程三要素主要是指原子性,可见性,有序性,其中:
- 原子性:最小粒度的划分,即一个不可被分割的操作。Java 中的原子性指:一个或多个操作要么全部执行成功,要么全部执行失败。
- 有序性:程序执行的顺序是按照代码的先后顺序执行的。cpu 有可能会对指令进行重排序。
- 可见性:当多个线程访问同一个共享变量时,如果其中一个线程对其进行了修改操作,其它线程能立即获取到最新修改的值。
综上所述,并发的本质本身是提高运行在单处理器上的程序的性能,实现并发最直接的方式是在操作系统级别使用进程,操作系统会自动隔离资源。但是对于像Java这样的会共享资源来说,在协调不同线程驱动的任务之间的资源使用,会使得某些资源无法被多个任务访问。因此,Java在顺序编程的基础上,支持对线程的控制,而且只对操作系统透明。
“X”程基本概述
在Java中,我们都知道应用程序(Application Program)的代码会被装载并且放入一个class里面,最后保存到一个拓展名为.java的文件中,然后通过命令工具和开发环境的编译,生成.class文件,最终托管给JVM虚拟机运行起来,从而实现我们要的反馈结果。在这些操作过程中,我们需要理解程序,进程,线程等几个关键概念,其中:
- 程序(Program):指一组指示计算机或其他具有信息处理能力装置执行动作或做出判断的指令,通常用某种程序设计语言编写,运行于某种目标计算机体系结构上。
- 进程(Process):计算机中的软件程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础,是系统分配资源和调度的基本单位,也就是说进程可以单独运行一段程序。
- 线程(Thead):进程中的一个实体,是被系统独立调度和分派的基本单位,是CPU调度和分派的最小基本单位,线程自己不拥有操作系统资源,但是该线程可与同属进程的其他线程共享该进程所拥有的全部资源。
从一定程度上来说,进程是程序的实体,而线程又是进程的实体,进程又是线程的容器。三者之间区别如下:
- 对于程序而言,程序并不能单独执行,是静止的,只有将程序加载到内存中,系统为其分配资源后才能够执行。
- 对于进程而言,程序对一个数据集的动态执行过程,一个进程包含一个或者更多的线程,一个线程同时只能被一个进程所拥有,进程是分配资源的基本单位。进程拥有独立的内存单元,而多个线程共享内存,从而提高了应用程序的运行效率。
- 对于线程而言,线程是进程内的基本调度单位,线程的划分尺度小于进程,并发性更高,线程本身不拥有系统资源,但是该线程可与同属进其他线程共享该进程所拥有的全部资源。每一个独立的线程,都有一个程序运行的入口、顺序执行序列和程序的出口。
综上所述,每个应用程序都使用一块内存区域,这个内存区域可以称为一个进程,内存区域中是需要执行代码的,具体执行代码就是线程去执行的。 需要注意的是:进程只是负责开辟内存空间的,线程才是负责执行代码逻辑的执行单元。
除了线程和进程外,我们更需要了解什么是管程,协程和纤程:
1.管程(Monitors):提供了一种机制,线程可以临时放弃互斥访问,等待某些条件得到满足后,重新获得执行权恢复它的互斥访问。
2.纤程(Fiber):是Microsoft组织为了帮助企业程序的更好移植到Windows系统,而在操做系统中增加的一个概念,由操作系统内核根据对应的调度算法进行控制,也是一种轻量级的线程。
3.协程(Coroutines):一种基于线程之上,但又比线程更加轻量级的存在,这种由程序管理的轻量级线程也被称为用户空间线程,对于内核而言是不可见的。正如同进程中存在多条线程一样,线程中也可以存在多个协程。协程在运行时也有自己的寄存器、上下文和栈,协程的调度完全由用户控制,协程调度切换时,会将寄存器上下文和栈保存到分配的私有内存区域中,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
⚠️[特别关注]:
1.纤程和协程的概念一致,都是线程的多对一模型,但有些地方会区分开来,但从协程的本质概念上来谈:纤程、绿色线程、微线程这些概念都属于协程的范围。
2. 2.纤程和协程的区别在于:纤程是OS级别的实现,而协程是语言级别的实现,纤程被OS内核控制,协程对于内核而言不可见。