Java 并发

并发问题的核心

在并发编程领域要解决的三个核心问题: 分工,同步,互斥

  • 分工: 将任务分解,进行执行典型的有生产者-消费者模型
  • 同步:分工好之后任务之间需要协作,需要通信,线程的执行顺序等问题都要解决
  • 互斥:同一时刻只允许一个线程访问共享资源,否则将引起混乱。锁的实现保证等

并发问题源头

1. 可见性

随着多核 CPU 的发展,缓存机制的引入,这就导致了主存中的变量或者数据同时存在于多个 CPU 的缓存中,这就导致了多个线程间数据的可见性问题。

2.原子性

CPU 在进行线程切换的时候采用时间片轮换方式,当一个线程A 的时间片用完但是线程任务未执行完,CPU 使用权被交给另外一个线程 B,此时 B按照相同的代码逻辑从 内存加载数据,执行操作,写回内存执行完毕。此时 A 又回来开始执行未执行完的操作,这时 A 所操作的那份数据的拷贝对内存数据来说已经为老版本了,在此数据上继续操作将覆盖掉 B 所做的更新,导致不期望的执行结果。上述的操作就破坏了原子性,当一个或多个操作在 CPU 执行过程中不被中断的特性称为原子性。

3.有序性

有序性问题常源自编译器优化带来的指令重排序带来的一些问题导致程序执行过程中出现异常结果的现象。

Java 解决并发问题

1.解决可见性

a. volatile 关键字

通过强制不使用 CPU 缓存,直接从内存中读取和写入

b.happens-before 原则 (前一个操作的结果对后续操作可见)

  • 程序顺序性原则: 代码顺序
  • volatile 变量:写操作 happens-before 后续对该变量的读操作
  • 传递性 A happens-before B,B happens-before C 则 A happens-before C
  • 管程中锁: 解锁 happens-before 于加锁
  • 线程 start 规则: A 线程调用 B start 则 B 可以看到 A start 之前的操作(共享变量)
  • 线程 join 规则:A join B 则 A 等 B 执行完返回后可以看到 B 的操作

You'll only receive email when qingliu publishes a new post

More from qingliu