第11讲心得
该讲介绍了局部变量为什么是安全的。
- 每个方法在调用栈中都有自己独立的空间,称为栈帧。每个栈帧中都有方法需要的参数和返回地址。调用方法时会创建新的栈帧并压入调用栈;方法返回时对应的栈帧就被自动弹出。也就是说,栈帧是和方法同生共死的。
- 局部变量的作用域是方法内部,也就是说局部变量也是和方法同生共死的。事实上,局部变量也放入了栈帧中。
- 两个线程可以用不同的参数调用同一个方法,那么线程和调用栈是什么关系呢?每个线程都有自己的调用栈,局部变量保存在各自的调用栈中。由于局部变量不会共享,所以没有并发问题。
- 仅在单线程内访问数据称为线程封闭。
第12讲心得
该讲介绍了如何用面向对象思想写好并发程序。
- 面向对象中有一个很重要的特性叫做封装,它是指将属性放入对象内部,外部对象只能通过本类提供的公共方法来间接访问这些属性。利用面向对象思想写并发程序的思路就是:将共享变量放入对象内部,对所有公共方法制定并发访问策略。
- 并发访问策略可分为三种:避免共享,也就是利用线程本地存储以及为每个任务分配独立的线程;不变模式,如Actor模式、CSP模式和函数式编程;管程及其它同步工具,管程是万能解决工具,但针对特定场景最好选用并发包提供的特定工具。
第14讲心得
该讲介绍了Lock。
- Java并发包通过Lock和Condition实现了管程,其中前者用于互斥,后者用于同步。
- 破坏死锁时可以选用破环不可抢占条件的方案。但synchronized做不到这一点:synchronized申请资源失败时线程会直接进入阻塞状态。
- Lock解决了这个问题。它提供了多种锁的变种:能够响应中断;支持超时;非阻塞获取。
// 支持中断的API
void lockInterruptibly()
throws InterruptedException;
// 支持超时的API
boolean tryLock(long time, TimeUnit unit)
throws InterruptedException;
// 支持非阻塞获取锁的API
boolean tryLock();
第15讲心得
本讲介绍了Condition。
- 调用方创建一个子线程,在子线程中执行方法调用,这种调用我们称为异步调用;方法实现的时候,创建一个新的线程执行主要逻辑,主线程直接 return,这种方法我们称为异步方法。
- 利用两个Condition作为条件变量可以实现阻塞队列。