# 线程安全与锁优化
## 线程安全
当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的。
*弱化* 如果把“调用这个对象的行为”限定为“单次调用”,这个定义的其他描述也能够成立的话,我们就可以称它是线程安全了。
### Java语言中的线程安全
#### 不可变
不可变(Immutable)的对象一定是线程安全的。
#### 绝对线程安全
Vector的get()、remove()和size(),如果另一个线程恰好在错误的时间里删除了一个元素,导致序号i已经不再可用的话,再用i访问数组就会抛出一个ArraylndexOutOfBoundsException
#### 相对线程安全
相对的线程安全就是我们通常意义上所讲的线程安全,它需要保证对这个对象单独的操作是线程安全的,我们在调用的时候不需要做额外的保障措施,但是对于一些特定顺序的连续调用,就可能需要在调用端使用额外的同步手段来保证调用的正确性。
#### 线程兼容
线程兼容是指对象本身并不是线程安全的,但是可以通过在调用端正确地使用同步手段來保证对象在并发环境中可以安全地使用。
### 线程安全的实现方法
#### 互斥同步(Mutual Exclusion & Synchronization)
同步是指在多个线程并发访问共享数据时,保证共享数据在同一个时刻只被一个(或者是一些,使用信号量的时候)线程使用。而互斥是实现同步的一种手段,临界区(Critical Section)、互斥量(Mutex)和信号量(Semaphore)都是主要的互斥实现方式。
在Java中,最基本的互斥同步手段就是synchronized关键字。
synchronized同步块对同一条线程来说是可重入的,不会出现自己把自己锁死的问题。
同步块在已进入的线程执行完之前,会阻塞后面其他线程的进入。
对于synchronized,虚拟机本身也会进行一些优化,譬如在通知操作系统阻塞线程之前加入一段自旋等待过程,避免频繁地切人到核心态之中。
相比synchronized,ReentrantLock增加了一些高级功能,主要有以下3项:
- 等待可中断
等待可中断是指当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情,可中断特性对处理执行时间非常长的同步块很有帮助�