目录
- 概述
- 线程与锁
- 函数式编程
- Clojure之道-分离标识与状态
- Actor
- 通信顺序进程
- 数据并行
- Lambda 架构
- 结束
概述
- 并发 VS 并行
- 并行架构
- 并发:不只是多核
- 七个模型
线程与锁
Day 1 - 互斥与内存模型
学习:如何创建线程;Java 对象内置锁实现互斥;线程与锁模型的三个主要危害:竞态条件、死锁、内存可见性;
线程与锁模型,在不同编程语言中普遍适用的原理:
- 对共享变量的所有访问都需要同步化
- 读线程和写线程都需要同步化
- 按照约定的全局顺序来获得多把锁(对象的散列值)
- 当持有锁时避免调用外星方法
- 持有锁的时间尽可能短
Day 2 - 超越内置锁
- 内置锁的限制:
- 一个线程等待内置锁进入阻塞之后,无法中断线程
- 尝试获取内置锁时,无法设置超时
- 获得内置锁,必须使用 Synchronized 块
- ReentrankLock 提供显式的Lock 与 Unlock 方法,可解决上述限制。
Lock lock = new ReentrankLock();
lock.lock();
try{
//...
}finally{
lock.unlock();
}
可中断的锁-ReentrankLock.lockInterruptibly()
超时-ReentrankLock.tryLock() -> 活锁现象影响(所有死锁线程同时超时,极有可能重现陷入死锁)
交替锁(hand-over-hand locking)
条件变量 ReentrankLock.newCondition()
原子变量 java.util.concurrent.atomic, 无锁非阻塞
学习:java.util.concurrent.lock; java.util.concurrent.atomic;
Day 3 - 站在巨人肩上
Java.util.concurrent;
创建线程终极版-使用线程池
写入时复制, copyOnWriteArrayList 监听器更高效
线程池应该多大:CPU 密集型,线程池大小接近核数;IO 密集型,线程池可以更大一些。最佳方式是真实环境压测来衡量性能。
-
词频统计
java.util.concurrent.ArrayBlockingQueue 实现生产者与观察者直接的高效协作; java.util.concurrent.ConcurrentHashMap 更高效的并发;
总结
线程与锁模型优点是适用面很广,更接近本质,易于指令式、面向对象语言中实现;缺点没有为并行提供直接支持,不适用于分布式内存模型、不适用于单个系统无力解决的问题。
难点: 难于测试、可维护性低。