一、lock是juc包中多线程重要接口,一般将之与synchronized锁进行比较
1.synchronized是java的一个关键字,作用在jvm层面,而lock是java一个接口
2.synchronized可以作用在方法和代码块,lock只能作用在代码块
3.synchronized不需要手动释放锁,lock需要在finally里面手动释放锁
4.synchronized是阻塞式加锁,lock中trylock方法支持非阻塞式加锁
5.synchronized没有超时机制,lock中trylcok方法可以支持超时机制
6.synchronized不可中断,lock中lockInterruptibly方法可中断的获取锁
7.synchronized是非公平锁,lock可以是公平锁也可以是非公平锁
8.synchronized用object的notify方法进行唤醒,lock用condition进行唤醒。
9.lock有ReadWriteLock实现类支持并发读
二、lock具体用法
1.Lock 是一个接口,ReentrantLock是它唯一的实现类,lock有以下几个方法:
1.1 lock() 方法
lock() 方法是平常使用得最多的一个方法,就是用来获取锁 。如果锁已被其他线程获取,则进行等待 。
使用方法:
Lock lock = new ReentrantLock();
lock.lock();
try{
//处理任务
}catch(Exception ex){
} finally{
lock.unlock(); //释放锁
}
1.2 tryLock()方法与 tryLock(long time, TimeUnit unit)方法
tryLock() 方法是有返回值的,它表示用来 尝试获取锁,如果获取 成功,则返回 true,如果获取 失败(即锁已被其他线程获取),则返回 false,也就说这个方法无论如何都会 立即返回 。在拿不到锁时不会一直在那等待 。
使用方法:
Lock lock = new ReentrantLock();
if(lock.tryLock()) {
try{
// 处理任务
}catch(Exception ex){
// 抛出异常
} finally{
lock.unlock(); //释放锁
}
} else {
// 如果不能获取锁,则直接做其他事情
}
tryLock(long time, TimeUnit unit)方法 和 tryLock()方法是类似的,只不过区别在于这个方法 在拿不到锁时会等待一定的时间 ,在时间期限之内如果还拿不到锁,就返回 false 。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true
注意:如果采用 Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁。因此一般来说,使用 Lock 必须在 try{}catch{}块 中进行,并且 将释放锁的操作放在 finally块 中进行,以保证锁一定被被释放,防止死锁的发生。
1.3 lockInterruptibly() 方法
lockInterruptibly() 方法比较特殊,当通过这个方法去获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。也就使说,当两个线程同时通过 lock.lockInterruptibly() 想获取某个锁时,假若此时线程A 获取到了锁,而线程B只有在等待,那么对线程B调用threadB.interrupt() 方法能够中断线程B的等待过程 。由于 lockInterruptibly() 的声明中抛出了异常,所以lock.lockInterruptibly() 必须放在 try块 中或者在调用 lockInterruptibly() 的方法外声明抛出InterruptedException 。
完整的例子:
package com.han.demo01;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
public static void main(String[] args) {
Data01 data = new Data01(