串行、并发、并行

假设有 3 件事要处理,A(实际投入 5 分钟,等待 10 分钟)B(实际投入 2 分钟,等待 8 分钟)C(实际投入 10 分钟,等待 0 分钟)

  • 串行:一个人先做 A,A 完成后做 B,依次做 C
  • 并发:一个人先做 A,5 分钟后 A 进入等待,此时去做 B,两分钟后再做 C
  • 并行:投入 3 个人,没人一个活,同时进行

Thread-2

可见并行的效率最高。

从软件的角度,串行是单进程单线程,并发为单进程多线程,并行为多进程。其次并发未必比串行效率更高,后续会体现出来。

从硬件的角度,因为时间片分配的技术,同一时间段内可以运行多个线程,因此一个处理器就可以并发。而并行需要多个处理器同一时刻各自运行一个线程来实现

如果一个类在单线程环境下能够运作正常,并且在多线程环境下也运行正常,那么我们就称其是线程安全,反之称为非线程安全。Java 标准库中的一些类如 ArrayList、HashMap 和 SimpleDateFormate 都是非线程安全的。

原子是不可分割的意思。类似于数据库的事务,在多线程环境下,多个线程访问同一共享变量,可能出现脏读,不具有原子性,具体原因是 cpu 高速缓存和内存变量不一致导致的。

Java 中有两种方式来实现原子性:

  1. 锁。锁具有排他性能够保证一个共享变量在任意时刻只能被一个线程访问
  2. CAS 指令。它是由处理器提供的指令,与锁的的差别在于锁通常是在软件层次实现的,而 CAS 是在硬件(处理器和内存)层面实现的,可以被看做是“硬件锁”。