学习笔记Java中的锁Lock
Posted 棉花糖灬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习笔记Java中的锁Lock相关的知识,希望对你有一定的参考价值。
本文参考自:Java并发编程:Lock。
Lock锁并不是java内置的功能,其应用场景是在多线程并发访问时,为了避免冲突,需要每个线程先获取锁,避免其他线程的进入,等线程执行完后释放锁,允许其他线程进入。
1. Lock锁与synchronized同步的区别
- Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
- synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
- Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
- 通过Lock可以知道有没有成功获取锁,而synchronized却无法办到;
- Lock可以提高多个线程进行读操作的效率。
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时,此时Lock的性能要远远优于synchronized。
2. Lock接口的主要方法
Lock是java.util.concurrent.locks包中的一个接口,其主要方法有获取锁的方法:lock()、tryLock()、tryLock(long time, TimeUnit unit)和lockInterruptibly(),释放锁的方法unLock()。
(1) lock()方法
lock()方法用来获取锁,若其他锁被其他线程获取,则等待,直到获取到。所以说一个线程是使用完锁后一定要释放,否则会导致其他线程一直等待。一般会配合try-catch块进行使用,并在finally块中释放锁。
Lock lock = ...;
lock.lock();
try{
// 处理任务
}catch(Exception ex){
// 异常处理
}finally{
lock.unlock(); // 释放锁
}
(2) tryLock()方法
tryLock()方法与lock()方法类似,不同在于前者有返回值,当获取锁成功时则返回true,反之返回false。也就是说这个方法无论能不能获取到锁都会立即返回。
tryLock(long time, TimeUnit unit)方法在tryLock()方法的基础上会等待指定的时间,若时间过后还没获取锁才返回false。两者用法类似。
Lock lock = ...;
if(lock.tryLock()) {
try{
// 处理任务
}catch(Exception ex){
// 异常处理
}finally{
lock.unlock(); //释放锁
}
}else {
// 如果不能获取锁,则直接做其他事情
}
(3) lockInterruptibly()方法
lockInterruptibly()方法获取锁后允许线程主动终止等待,即若有线程1和线程2两个线程同时使用lockInterruptibly()方法获取锁,且线程1获得了锁,而线程2在等待,那么使用thread2.interrupt()方法能够终止线程2的等待。实际上该方法不仅能打断在等待中的线程,也可以打断已获取锁的线程。该方法无返回值。
Lock lock = ...;
lock.lockInterruptibly();
try{
// 处理任务
}catch(Exception ex){
// 异常处理
}finally{
lock.unlock(); // 释放锁
}
3. 实例
ReentrantLock即可重入锁,它是Lock接口的一个实现类。
public class LockTest {
public static void main(String[] args) {
// 可重入锁,Lock接口的一个实现类
ReentrantLock reentrantLock = new ReentrantLock();
Runnable runnable = new Runnable() {
@SneakyThrows
@Override
public void run() {
// 获取锁
reentrantLock.lockInterruptibly();
try {
System.out.println(Thread.currentThread().getName() + "获取了锁");
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 最终都要释放锁
reentrantLock.unlock();
System.out.println(Thread.currentThread().getName() + "释放了锁");
}
}
};
Thread thread1 = new Thread(runnable, "Thread1");
Thread thread2 = new Thread(runnable, "Thread2");
thread1.start();
thread2.start();
try {
// 主线程睡2s
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
// 打断thread2,停止等待
thread2.interrupt();
System.out.println("Thread2停止等待");
}
}
其输出为,其中双斜杠后的为注释:
Thread1获取了锁 // 第0秒
Thread2停止等待 // 第2秒
$报错信息$ // 第2秒
Thread1释放了锁 // 第5秒
以上是关于学习笔记Java中的锁Lock的主要内容,如果未能解决你的问题,请参考以下文章
java学习第22天(关于java中的锁LOCK及多线程的面试题)
并发包java.util.concurrent.locks.Lock