Lock框架简介
1 Lock接口
1.1 前言
- 锁是控制多线程访问一个共享资源的工具。通常一把锁对一个共享资源提供排外的访问,也即某个时候只有一个线程可以获得这把锁,所有访问这个共享资源需要首先获取到这把锁(某些如ReadWriteLock允许并发访问共享资源);
- synchronized关键字提供访问任何一个对象关联的隐式(或内置)监控锁。使用synchronized编程简单方便而且可以规避一些涉及锁的常见编程错误。但是使用synchronized强制要求锁的获取和释放必须出现在一个块结构中,多个锁被获取时,越先被获取的锁越后被释放,并且所有锁必须在同一个作用域范围内被获取和释放。这种作用域机制在面对如下需求是不可实现的:
获取了A的锁,接着获取B的锁,接着释放A锁后获取C锁,接着释放B锁后再获取D锁…… - Lock接口实现相比于synchronized,对锁的获取和释放更灵活,性能更强,而且支持多个关联Contidion对象。Lock接口实现使在不同的作用域内获取和释放锁成为可能,并且允许多个锁间可以以任何顺序获取或释放。
1.2 定义
public interface Lock {
/**
* 获取锁
* 如果当前锁不可用时,当前的线程被禁止进行线程调度,并且处于休眠状态直到获取到锁为止。
*/
void lock();
/**
* 获取锁除非当前线程被Thread#interrupt中断了
* 如果当前锁不可用时,当前的线程被禁止进行线程调度,并且处于休眠状态直到下面两种情况发生:
* 1.当前线程获取了锁
* 2.其他线程中断了当前线程并且支持锁获取中断
*/
void lockInterruptibly() throws InterruptedException;
/**
* 仅当调用时锁是可用时获取这锁(Acquires the lock only if it is free at the time of invocation)
* 如果调用时锁是可用的,调用获取锁并立即返回true
* 如果调用时锁是不可用的(别其他线程占有),该函数立即返回false
*/
boolean tryLock();
/**
* 如果在给定时间内锁是可用的并且当前线程没被其他线程中断就获取该锁
* 如果锁是可用的,改函数立即返回true
* 如果当前锁不可用时,当前的线程被禁止进行线程调度,并且处于休眠状态直到下面三种情况发生:
* 1.当前线程获取了锁
* 2.其他线程中断了当前线程并且支持锁获取中断, 抛出InterruptedException
* 3.指定等待时间过去了(指定时间不大于0不等待),该函数立即返回false
*/
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
/**
* 释放锁
*/
void unlock();
/**
* 返回一个新Condition实例,这个Contdition实例是跟Lock实例绑定的
* 当前线程必须持有锁才能让condition等待
* Condition#await()调用后将自动释放这个锁然后进入等待,当await返回后重新获取这个锁
* 如果当前Lock实现不支持conditions抛出UnsupportedOperationException
*/
Condition newCondition();
}
个人小结:lock和lockInterruptibly区别在于在等待锁过程中lockInterruptibly可响应中断并退出等待;
1.3 ReentrantLock类图
2 Condition接口
2.1 定义
public interface Condition {
/**
* 促使当前线程等待直到被signalled或者被Thread#interrupt中断
* 关联上这个Condition的锁自动释放,当前线程被禁止进行线程调度,并且处于休眠状态直到下面四种情况发生:
* 1.其他线程调用了这个Condition的signal方法并且当前线程正好被唤醒
* 2.其他线程调用了这个Condition的signalAll方法
* 3.其他线程中断了当前线程并且支持锁获取中断, 抛出InterruptedException,中断状态位被清除
* 4.指定等待时间过去了(指定时间不大于0不等待),该函数立即返回false
* 在以上所有情形中,在这个方法返回前当前线程必须重新获取到这个Condition关联的锁
*/
void await() throws InterruptedException;
/**
* 促使当前线程等待直到被signalled
* 关联上这个Condition的锁自动释放,当前线程被禁止进行线程调度,并且处于休眠状态直到下面三种情况发生:
* 1.其他线程调用了这个Condition的signal方法并且当前线程正好被唤醒
* 2.其他线程调用了这个Condition的signalAll方法
* 3.一个虚假的(spurious)唤醒发生了
* 在以上所有情形中,在这个方法返回前当前线程必须重新获取到这个Condition关联的锁
* 如果当前线程进入这个方法是它的中断状态位被设置或者被Thread#interrupt中断,处于等待时,它将继续等待直到
* 被signalled。当方法返回时,这个中断状态位还是被设置了。
*/
void awaitUninterruptibly();
/**
* 促使当前线程等待直到被signalled或者被Thread#interrupt中断或者指定等待时间到了
* 关联上这个Condition的锁自动释放,当前线程被禁止进行线程调度,并且处于休眠状态直到下面五种情况发生:
* 1.其他线程调用了这个Condition的signal方法并且当前线程正好被唤醒
* 2.其他线程调用了这个Condition的signalAll方法
* 3.其他线程中断了当前线程并且支持锁获取中断, 抛出InterruptedException,中断状态位被清除
* 4.指定等待时间过去了
* 5.一个虚假的(spurious)唤醒发生了
* 在以上所有情形中,在这个方法返回前当前线程必须重新获取到这个Condition关联的锁
* @return nanosTimeout参数值减去该函数等待的时间的差值
*/
long awaitNanos(long nanosTimeout) throws InterruptedException;
/**
* 促使当前线程等待直到被signalled或者被Thread#interrupt中断或者指定等待时间到了
* 该方法等效于awaitNanos(unit.toNanos(time)) > 0
*/
boolean await(long time, TimeUnit unit) throws InterruptedException;
/**
* 促使当前线程等待直到被signalled或者被Thread#interrupt中断或者截止时间到了
* 关联上这个Condition的锁自动释放,当前线程被禁止进行线程调度,并且处于休眠状态直到下面五种情况发生:
* 1.其他线程调用了这个Condition的signal方法并且当前线程正好被唤醒
* 2.其他线程调用了这个Condition的signalAll方法
* 3.其他线程中断了当前线程并且支持锁获取中断, 抛出InterruptedException,中断状态位被清除
* 4.指定截止时间过去了
* 5.一个虚假的(spurious)唤醒发生了
* @return 如果截止时间已经过去了返回false,否则返回true,实例如下:
*/
boolean awaitUntil(Date deadline) throws InterruptedException;
/**
* 唤醒一个等待线程
* 从等待这个Contidion中所有线程中选择一个线程唤醒,这个唤醒线程在await方法返回之前重新获取该锁
*/
void signal();
/**
* 唤醒所有等待线程
* 任何等待这个Contidion的所有线程都将被唤醒,每个唤醒线程在await方法返回之前重新获取该锁
*/
void signalAll();
}