一、lock接口规范
void lock(); //加锁,同synchronized void lockInterruptibly() //加锁,等待锁期间可被打断 boolean tryLock(); //尝试获取锁,仅尝试一次 boolean tryLock(long time, TimeUnit unit) //尝试获取锁,time时间内循环尝试获取多次 void unlock(); //解锁 Condition newCondition(); //条件变量,同synchronized的wait/notify
面试题1:synchronized与lock都可以实现悲观锁,如何选择?
jdk1.6之后,synchronized与ReentrantLock二者的性能差异不再是选谁的主要因素,你在做选择的时候更应该考虑的是其易用性、功能性和代码的可维护性,二者30%的性能差异决定不了什么,因此当synchronized满足不了功能时,再选用lock。
面试题2:lock比synchronized多出哪些功能?
1、等待锁期间可被打断;
2、锁超时;
3、可以实现公平锁;
4、可以设置多个条件变量、可以精准唤醒
二、lock接口使用案例
2.1 lock方法使用案例
lock方法,与synchronized关键字功能相同
Lock lock=new ReentrantLock();
lock.lock();
try{
//处理任务
}catch(Exception ex){
}finally{
lock.unlock(); //释放锁
}
2.2 lockInterruptibly()使用案例
lockInterruptibly()在等待锁期间,可以被打断,二lock不能。
public void method() throws InterruptedException {
lock.lockInterruptibly();
try {
//.....
}
finally {
lock.unlock();
}
}
备注:
synchronized中,当线程处于
wait()
等待状态时,调用线程对象的interrupt()
方法会中断线程等待状态。而不是在等待锁期间被打断。
2.3 newCondition()方法使用案例
关键字synchronized
与wait()/notify
这两个方法一起使用可以实现等待通知模式。
在Lock
显示锁中,newConditon()
方法返回Condition对象
,Condition
类也可以用await/signal
实现等待通知模式。
实例:两个线程交替打印
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionTest02 {
public static void main(String[] args) {
MyService myService = new MyService();
//创建打印线程
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
myService.printOne();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
myService.printTwo();
}
}
}).start();
}
static class MyService{
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private volatile boolean flag = true; //打印标志
/**
* 打印方法 ----
*/
public void printOne(){
try {
lock.lock();
while(!flag){
condition.await();
}
System.out.println(Thread.currentThread().getName()+"----------One-------");
flag=false;
condition.signal(); //通知领完的线程打印
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
/**
* 打印方法2
*/
public void printTwo(){
try {
lock.lock();
while(flag){
condition.await();
}
System.out.println(Thread.currentThread().getName()+"**********TWO********");
flag=true;
condition.signal(); //通知领完的线程打印
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
输出
Thread-0----------One-------
Thread-1**********TWO********
Thread-0----------One-------
Thread-1**********TWO********
Thread-0----------One-------
Thread-1**********TWO********