2020-01-31 Java线程安全和并发编程知识总结。

一直以来,关于多线程编程和线程安全的知识和各种工具,在工作中实际都已经全部用到了。但都是根据业务需要,零零散散的使用,没有进行过总结。一直想将并发编程的知识点总结一下,但一直没有时间。最近冠状病毒肺炎肆虐,春节多了10天假,也不能出门,就正好把这个事情做了。

写本文的目的,只是将相关知识点简单总结并罗列一下,方便从总体上快速浏览并了解整个并发编程和线程安全体系,但不做深入分析。因为每一个知识点,一旦深入分析,都可以和其他知识点结合起来,会非常复杂。且在网上,都可以找到每一个单独知识点深入分析的文章。

并发和线程安全的基础概念

关于并发编程所需的基础概念,进程、线程、信号量、中断、阻塞、32位/64位,大学《操作系统》课程上就有;CPU、多核CPU、寄存器、内存,是《计算机原理》课程的基础知识;这些都是构成并发编程的基础,就不总结了。

同步本身,包含两层含义:内存可见性和操作原子性。

内存可见性

  • 变量或对象是存放在内存中的。
  • 当一个线程修改某个变量或对象时,其他线程在同一个时间,可能读取到的是修改前的值,也可能是修改后的值。
  • 当一个线程修改变量或对象后,能确保其他线程能及时读取到修改后的值,称为该变量对其他线程可见。

内存可见性产生的原理如下:

  1. 所有的变量,都存储在主内存中。
  2. 当启动线程时,会为每个线程分配自己专有的工作内存区域,并将相关变量从主内存拷贝到工作内存区域。
  3. 当线程修改了某个变量时,先修改自己的内存工作区域中的变量副本,再将该值刷到主内存中的变量;其他线程需要将更新后的主内存变量,更新到自己的线程工作内存区域中的变量副本。
  4. 当一个线程更改了自己的线程工作内存区域中的变量后,没能及时刷新到主内存中的变量,或没能刷新到其他线程的内存工作区域中,就会导致不同线程看到的同一个变量的值,出现不同。就是内存可见性问题。

原子性

  • 在线程中,由多个操作组成的一组复合操作,以不可分割的方式被执行,称为原子性。
  • 当一个线程进行原子操作时,其他线程不会读取到该操作过程中的尚未完成修改的变量值;当一个线程尚未开始原子操作时,其他线程只会读取到尚未被修改的值;当一个线程开始原子操作后,其他线程只会读取到该原子操作完成后,修改结束的值。

1. Java语言提供的基本线程安全保护

本章节总结java语言本身自带的线程安全相关的知识点。

2 JDK提供的线程安全工具

2.1 原子量工具包(java.util.concurrent.atomic

2.2 锁工具包(java.util.concurrent.lock

在这个包中,提供了锁的接口,以及各种常用锁实现。

锁的原理,是一个线程进入被锁保护的代码前,需要先申请锁;如果申请成功,则进入代码块;如果申请失败,则阻塞到别人释放锁;从而确保只有一个线程在执行被保护的代码。

最常用的,是通过 synchronized关键词使用对象的内置锁。在1. Java语言提供的基本线程安全保护的1.2章节对该关键词有详细描述。

2.2.1 可重入锁与不可重入锁。

2.2.2 条件锁 Condition

2.2.3 读写锁 ReadWriteLock

2.3 闭锁 CountDownLock

2.4 信号量 Samaphore

2.5 TODO 栅栏 Barrie 和 Exchanger

2.6 TODO 同步容器类(都在java.util.concurrent下)

2.6.1 TODO Vector

2.6.2 TODO ConcurrentMap(4个子类)

2.6.3 TODO

2.7 线程池工具

3 TODO 通过设计模式实现的线程安全

3.1 线程封闭

3.2 TODO

你可能感兴趣的:(2020-01-31 Java线程安全和并发编程知识总结。)