参考了 《Java核心技术》 卷I 第14章 多线程 14.5.5-14.6
synchronized 关键字
先来总结一下使用Lock和Condition对象的关键:
- 锁用来保护代码片段,任何时刻只有一个线程执行被保护的代码
- 锁可以拥有一个或多个条件对象
- 每个条件对象管理进入被保护的代码片段,但还不能运行的线程
Lock和Condition接口提供了高度的锁定控制,Java中的每个对象都有一个内部锁,如果方法用synchronized关键字生命,那么对象所将保护整个方法,也就是说要调用该方法,线程必须获得内部对象锁。
也就是以下这两种是等价的:
|
|
|
|
因此对Bank类的transfer方法声明为synchronized,而不需要使用一个显示的锁。而wait和notifyAll方法等价于:
|
|
还可以通过synchronized关键字获得一个对象锁
|
|
这里使用lock对象的目的就是用lock对象的内部锁(也就是所有Java对象都有的锁)
有时候,仅仅为了读写一个或两个实例域就使用同步,开销很大,volatile关键字为实例域的同步访问提供了一种免锁机制,如果声明一个域为volatile,那么编译器和虚拟机就知道可能有多线程并发访问此变量的情况。因此编译器就会加入一些代码保证并发访问这个域的正确性,但是volatile变量不能保证原子性:
|
|
还可以用final变量安全地访问一个共享域,因为其他线程实在完成构造之后看到final变量的。
线程局部变量
如果想为每个线程构造一个实例:
|
|
然后具体调用:
|
|
在一个给定线程首次调用get方法时,会调用其初始化代码。
锁测试和超时
|
|
tryLock先试图申请一个锁,成功后返回true,否则返回false,而且线程可以立即离开做其他事情。tryLock也可以使用超时参数
|
|