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 并发编程的艺术>