用 Java 并发编程实践中的话,编写正确的程序并不容易,而编写正常的并发程序就更难了!-达内科技整理
相比于顺序执行的情况,多线程的线程安全问题是微妙而且出乎意料的,因为在没有进行适当同步的情况下多线程中各个操作的顺序是不可预期的.
并发编程相比 Java 中其他知识点学习起来门槛相对较高,学习起来比较费劲,从而导致很多人望而却步;
而无论是职场面试和高并发高流量的系统的实现却都还离不开并发编程,从而导致能够真正掌握并发编程的人才成为市场比较迫切需求的.
本 Chat 作为 Java 并发编程之美系列的并发编程必备基础晋级篇,通过通俗易懂的方式来和大家聊聊多线程并发编程中涉及到的高级基础知识(建议先阅读《Java 编程之美 - 线程相关的基础知识》),具体内容如下:
什么是多线程并发和并行.
什么是线程安全问题.
什么是共享变量的内存可见性问题.
什么是 Java 中原子性操作.
什么是 Java 中的 CAS 操作,AtomicLong 实现原理
什么是 Java 指令重排序.
Java 中 Synchronized 关键字的内存语义是什么.
Java 中 Volatile 关键字的内存语义是什么.
什么是伪共享,为何会出现,以及如何避免.
什么是可重入锁、乐观锁、悲观锁、公平锁、非公平锁、独占锁、共享锁.
多线程并发与并行
首先要澄清并发和并行的概念,并发是指同一个时间段内多个任务同时都在执行,并且都没有执行结束;而并行是说在单位时间内多个任务同时在执行;
并发任务强调在一个时间段内同时执行,而一个时间段有多个单位时间累积而成,所以说并发的多个任务在单位时间内不一定同时在执行.

在单个 CPU 的时代多个任务同时运行都是并发,这是因为 CPU 同时只能执行一个任务,单个 CPU 时代多任务是共享一个 CPU 的,当一个任务占用 CPU 运行时候,其它任务就会被挂起,当占用 CPU 的任务时间片用完后,会把 CPU 让给其它任务来使用.
所以在单 CPU 时代多线程编程的意义不大,并且线程间频繁的上下文切换还会带来开销.
如下图单个 CPU 上运行两个线程,可知线程 A 和 B 是轮流使用 CPU 进行任务处理的,也就是同时 CPU 只在执行一个线程上面的任务,当前线程 A 的时间片用完后会进行线程上下文切换,也就是保存当前线程的执行线程,然后切换线程 B 占用 CPU 运行任务.
而在多线程编程实践中线程的个数往往多于 CPU 的个数,所以平时都是称多线程并发编程而不是多线程并行编程.
线程安全问题
谈到线程安全问题不得不先说说什么是共享资源,所谓共享资源是说多个线程都可以去访问的资源.
线程安全问题是指当多个线程同时读写一个共享资源并且没有任何同步措施的时候,导致脏数据或者其它不可预见的结果的问题.
线程 A 和线程 B 可以同时去操作主内存中的共享变量,是不是说多个线程共享了资源,都会产生线程安全问题呢?
答案是否定的,如果多个线程都是只读取共享资源,而不去修改,那么就不会存在线程安全问题.
只有当至少一个线程修改共享资源时候才会存在线程安全问题.最典型的就是计数器类的实现,计数 count 本身是一个共享变量,多个线程可以对其进行增加一,如果不使用同步的话,由于递增操作是获取 -> 加1 -> 保存三步操作,所以可能导致导致计数不准确
假如当前 count=0,t1 时刻线程 A 读取了 count 值到本地变量 countA.
然后 t2 时刻递增 countA 值为1,同时线程 B 读取 count 的值0放到本地变量 countB 值为0(因为 countA 还没有写入主内存).
t3 时刻线程 A 才把 countA 为1的值写入主内存,至此线程 A 一次计数完毕,同时线程 B 递增 CountB 值为1.
t4 时刻线程 B 把 countB 值1写入内存,至此线程 B 一次计数完毕.
先不考虑内存可见性问题,明明是两次计数哇,为啥最后结果还是1而不是2呢?其实这就是共享变量的线程安全问题.
那么如何解决?这就需要在线程访问共享变量时候进行适当的同步,Java 中首屈一指的是使用关键字 Synchronized 进行同步,这个下面会有具体介绍.
共享变量的内存可见性问题
要谈内存可见性首先需要介绍下 Java 中多线程下处理共享变量时候的内存模型.
Java 内存模型规定了所有的变量都存放在主内存中,当线程使用变量时候都是把主内存里面的变量拷贝到了自己的工作空间或者叫做工作内存.
Java 内存模型是个抽象的概念,那么在实际实现中什么是线程的工作内存呢?
是双核 CPU 系统架构,每核有自己的控制器和运算器,其中控制器包含一组寄存器和操作控制器,运算器执行算术逻辑运算,并且有自己的一级缓存,并且有些架构里面双核还有个共享的二级缓存.
以上就是达内科技给大家做的内容详解,更多关于IT知识的学习,请继续关注达内科技