[Java 并发编程] 1. 并发和多线程

2020-08-09

1. 并发和多线程

并发编程
并发编程涵盖了多线程技术在内,指并发执行任务时可能出现的问题,使用的多线程技术,以及解决方案。

多线程:
同一个应用程序中,多个线程同时执行。

多线程应用程序:
多线程应用程序是一个多 CPU 同时执行不同的线程的应用程序。如图

一个线程不等于一个CPU,通常情况下一个CPU在不同时间段交换执行不同的线程,不同的CPU同时执行不同的线程。如图:


2. 为什么使用多线程

  • 更好的利用单 CPU 资源
  • 更好的利用多 CPU 或 CPU 内核
  • 更快速的响应-提高用户体验
  • 更公平的响应-提高用户体验

更好的利用单 CPU 资源
单个CPU通过分配CPU时间片达到交换地执行不同线程的目的,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒。

更好的利用多 CPU 或 CPU 内核
创建多个线程,充分地利用多个CPU同时执行不同的线程,加快程序执行速度,充分利用多CPU资源。

更快速的响应-提高用户体验
充分的利用单CPU资源和多CPU资源都能够加快程序的执行速度,以提高用户体验

更公平的响应-提高用户体验
不同的线程在单CPU中分配CPU时间片交换执行,在某些特定情况下以一种更加公平的方式执行不同的线程。比如某个线程需要调用网络资源或者其他的操作需要长时间占用CPU,导致许多线程需要等待CPU去执行,造成阻塞。


3. 使用多线程不一定更快

由于线程的创建和上下文的切换的开销,多线程的执行效率不一定比单线程的执行效率更好。

线程创建的方式

  • 继承Thread类,重写 run() 方法
  • 实现Runnable接口,重写 run() 方法
  • 实现Callable接口,重写 call() 方法

上下文切换
单核处理器也支持多线程执行代码,CPU 通过给每个线程分配CPU时间片来实现这个机制。当前任务执行一个时间片后会切换到下一个任务。但是切换前会保存上一个任务的状态,以便于下次切换到该任务时,可以再加载这个任务的状态。任务从保存到再加载的过程就是一次上下文切换。


4. 多线程 vs. 多任务

多任务
不同CPU同时执行不同的应用程序的不同线程。

多线程
不同CPU同时执行相同的应用程序的不同线程。

多线程技术更难实现
多线程技术可以以一种很好的方式提高某些类型的应用程序的性能。但是多线程技术比多任务技术要面临更多的技术挑战。不同的线程在同一个应用程序中同时执行,它们可能存在一个线程在读取共享内存的数据,另外一个线程在写入数据至共享内存,造成线程不安全的问题发生,以至于产生了单线程技术通常情况下不会发生的错误。

现代计算机通常拥有多个CPU或者多个CPU内核,这意味着不同的线程可以被不同的CPU同时执行。如图


5. Java 中的并发和多线程

并发模型

  • 共享状态并发模型(shared state concurrency model)
  • 隔离状态并发模型(separate state concurrency model)

共享状态并发模型
同一个应用程序中的不同的线程使用了同一个共享对象(或变量)。在共享状态并发模型中存在很多问题,这些问题难以完美地解决。

隔离状态并发模型
同一个应用程序中的不同的线程不共享任何对象(或变量)。


Java 并发学习指南

并发和多线程理论知识

  • 多线程的好处
  • 多线程的成本
  • 并发模型
  • 同一线程
  • 并发 vs. 并行

Java并发的基础理论知识

  • 创建和开始一个线程
  • 线程安全和共享资源
  • 线程安全和不变性
  • JMM (Java memory model)
  • synchronize 关键字
  • volatile 关键字
  • ThreadLocal

Java 并发常见问题

  • 死锁
  • 预防死锁

Java 提供的一些解决常见问题的工具

  • Lock (锁)
  • Read / Write Lock (读写锁)
  • ReentrantLock (可重入锁)
  • Semaphores (信号)
  • Blocking Queues (阻塞队列)
  • Thread Pools (线程池)
  • Compare and Swap (CAS)

Java 并发工具包 (JUC: java.util.concurrent)

  • Java Concurrency Utilities - java.util.concurrent

推荐

<Java 并发编程的艺术>