-
JUC中的
Executor
、 Fork/Join
和 Future
本质上都是一种 分工
方法
-
并发编程领域还总结了一些 设计模式
,基本上都是和 分工
方法相关
Thread-Per-Message
Worker Thread
同步
-
在并发编程领域里的 同步
,主要指的就是
线程间的协作
- 一个线程执行完了一个任务,如何通知执行后续任务的线程开始工作
-
协作一般是与分工相关的
-
JUC中的
Executor
、 Fork/Join
和 Future
本质上都是一种 分工
方法
-
但同时也能解决 线程协作
的问题
-
例如,用
Future
可以发起一个 异步
调用
- 当主线程调用get()方法取结果时,主线程会等待
- 当异步执行的结果返回时,get()方法就自动返回了
-
Future
工具类已经帮我们解决了
主线程和异步线程之间的协作
-
JUC中的
CountDownLatch
、 CyclicBarrier
、 Phaser
和 Exchanger
都是用来解决 线程协作
问题的
-
但很多场景还是需要自己处理线程之间的协作,问题基本可以描述为
-
当某个条件不满足时,线程需要等待,当某个条件满足时,线程需要被唤醒执行
-
在Java并发编程领域,解决 协作
问题的 核心技术
是 管程
(Monitor)
-
上面提到的所有线程协作技术 底层
都是利用 管程
来解决的
-
管程是一种解决并发问题的 通用模型
,除了能解决 线程协作
问题,还能解决 互斥
问题
-
管程是解决并发问题的万能钥匙
互斥
-
分工和同步主要强调的是 性能
,线程安全关注的是
并发程序的正确性
-
在并发程序里,当多个线程 同时访问
同一个共享变量时,结果是 不确定
的
-
导致 不确定的主要源头
是 可见性问题,有序性问题和原子性问题
,为了解决这三个问题,Java引进来
Java内存模型
-
Java内存模型提供了一系列规则,可以避免可见性问题,有序性问题和原子性问题,但
不能完全解决线程安全的问题
-
解决 线程安全
问题的 核心方案
还是 互斥
,互斥的定义:
在同一时刻,只允许一个线程访问共享变量
-
实现互斥的 核心技术
是 锁
,
synchronized
、JUC中的各种 Lock
都能解决互斥问题
-
锁解决了 线程安全
的问题,但同时也带来了 性能问题
,可以针对场景进行优化
-
JUC中的
ReadWriteLock
、 StampedLock
可以优化在 读多写少
的场景下锁的性能
-
无锁的数据结构,例如JUC中的 原子类
都是基于 无锁
技术实现的
-
使用
Copy-On-Write
模式
-
不共享变量
(ThreadLocal)或者 变量只允许读
(final)
-
使用锁除了要注意性能之外,还需要注意 死锁
问题
原文
http://zhongmingmao.me/2019/04/10/java-concurrent-overview/