Lock介绍
在Java中实现锁可以使用Synchronized关键字,也可以使用Lock接口所提供的实现类。
ReentantLock是Lock的实现类,它除了能完成Synchronized所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁请求、定时锁等避免多线程死锁的方法。
Lock和Synchronized的区别
- 都是可重入锁
- Lock需要显示地获取和释放锁,繁琐,当能让代码更灵活
- Synchronized不需要显示地获取和释放锁,简单
- Lock是接口,是代码层面的实现,Synchronized是关键字,是依赖JVM实现
ReentrantLock独有的功能
- 可指定是公平锁还是非公平锁
- 提供了一个Condition类,可以分组唤醒需要唤醒的线程
- 提供能够中断等待锁的线程的机制,lock.lockInterruptibly()
Lock接口使用
public class LockTest extends Thread {
Lock lock=new ReentrantLock();
public void add() {
lock.lock();
try{
for(int i=0;i<20;i++) {
System.out.println(i+" "+Thread.currentThread().getName());
}
}finally{
lock.unlock();
}
}
@Override
public void run() {
add();
}
public static void main(String[] args) {
LockTest lockTest=new LockTest();
Thread thread1=new Thread(lockTest);
Thread thread2=new Thread(lockTest);
thread1.start();
thread2.start();
}
}
Condition控制线程间通信
Condition接口描述了可能会与锁有关联的条件变量,这些变量在用法上与使用Object.wait 访问隐式监视器类似,但提供了更强大的功能,特别指出的是,单个Lock可能与多个Condition对象关联。为了避免兼容性问题,Condition方法的名称与对应的Object版本中的不同 在Condition对象中,与wait、notify、notifyAll方法对应的分别是await、signal、signalAll。Condition实例实质上被绑定到一个锁上,要为特定Lock实例获得Condition实例,需要使用newCondition()方法
获得Condition对象
private Lock lock=new ReentrantLock();
private Condition condition=lock.newCondition();
通过Condition对象,可以实现线程的等待和唤醒
condition.await();
condition.signal();
condition.signalAll();