Java 并发知识梳理

vcjmhg 的个人博客 自律者自由 本文由博客端 https://www.vcjmhg.top 主动推送

概述

随着摩尔定律逐步失效,cpu 单核性能达到瓶颈,并发逐渐逐渐得到广泛应用,因而学习了解以及使用并发就显得十分重要。但并发相关的知识比较琐碎,不易系统学习,因而本篇文章参照王宝令老师《Java 并发编程》来勾勒出一张“并发全景图”。

是什么?

用学术定义来说就是

并发:同一时间段,多个任务都在执行 (单位时间内不一定同时执行);

简单来说就是,同一个时间段,让计算机同时做多个事情。

说到 并发,不得不提就是 并行

并行:单位时间内,多个任务同时执行。

两者大眼一看很像,仔细一想却并不相同,因为 并行 强调某个时间点多个任务同时执行,而 并发 强调的是一个时间段内多个任务都在执行

怎么做?

大部分并发问题,最终都可以抽象成三类问题分工同步互斥。而且针对不同的问题有着不同的方式来解决,具体如下图所示:

image.png

分工

所谓 分工,类似于现实中一个组织完成一个项目,项目经理要拆分任务,安排合适的成员去完成。

在并发编程领域,你就是项目经理,线程就是项目组成员。任务分解和分工对于项目成败非常关键,不过在并发领域里,分工更重要,它直接决定了并发程序的性能,并且分工非常重要且复杂,因而 Java 并发包中有一系列方法来实现 分工

基于分工思想设计的并发设计模式也有很多:

同步

同步 更多描述的是一种协同关系,在分完工之后,具体执行时,任务之间会有依赖,一个任务之后完成之后,其他依赖它的任务才能开始进行,因而就引入的 同步 来协同各个任务之间的执行顺序。

针对该类问题,Java 也提供了一系列工具来辅助解决:

互斥

分工、同步主要为了充分发掘 CPU 的性能来解决问题,但并发问题中,还需要解决正确性问题,即保证 线程安全

当多个线程同时访同一个变量时,最后执行的结果是不确定的,比如下边这段代码:

public class UnsafeSequence {
	private int value = 0;
	public int getNext() {
		return ++value;
	}
}

如果我们有多个线程同时调用 getNext() 时,多个线程之间推进顺序的不同可能会有不同的执行结果:

可能会是 2,递推顺序如下:

image.png

可能结果是 1,代码执行顺序如下:

image.png

因而结果是不确定的,也就是说结果可能是正确的(比如上边的程序执行结果为 2),可能是错误的(比如执行结果是 1),执行前是不知道的。而导致不确定的主要源头主要是三个问题可见性问题、有序性问题和原子性问题,为了解决这三个问题,Java 引入了内存模型,内存模型提供一系列规则利用这些规则,我们可以避免可见性问题、有序性问题,但是还不足以完全解决线程安全问题。解决线程安全问题的核心方案还是 互斥

所谓互斥,指的是同一时刻,只允许一个线程访问共享变量。

实现互斥主要手段是互斥锁主要包含下边这些手段:

除此之外,未来提高速度,也有一些无锁的方案:

总结

本文主要从分工、同步和互斥三类问题展开,从解决对应问题角度出发大致梳理了 Java 并发知识的学习前景图。后续将分若干部分来讲对应的内容。

引用

  1. 《深入理解 Java 虚拟机》
  2. 《Java 并发实战》
  • 并发
    71 引用 • 70 回帖 • 1 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    2935 引用 • 8124 回帖 • 659 关注

广告 我要投放

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...