ReentrantLock说明
Posted use-d
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReentrantLock说明相关的知识,希望对你有一定的参考价值。
ReentrantLock与synchronized一样都可以用来控制多线线程对共享资源的访问。
synchronized关键字是隐式的获得锁,即进入synchronized方法或者synchronized代码会自动的获得锁,离开同步方法或者同步代码块自动释放锁。
ReentrantLock相对于synchronized来说对锁的操作更加灵活,ReentrantLock可以显示的获得锁 和 释放锁。
对ReentrantLock锁的释放要写在finally代码块下,保证ReentrantLock获得锁后,一定会被释放。
不要将ReentrantLock获得锁的代码写在try代码块下,因为如果ReentrantLock获得锁时方式异常,异常抛出的同时会导致锁无故释放,然后在finally代码块中再释放ReentrantLock锁的话,会报错。
ReentrantLock提供的synchronized关键字不具备的主要特性:
- 尝试非阻塞的获得锁,当前线程获得锁时,如果锁已经被其他线程获得,可以立即返回false。
- 能被中断的获得锁,即当线程获得锁后,当前线程被中断后,当前线程可以继续运行。
- 超时获得锁,在指定时间内获得锁,如果在指定时间内获得锁则返回true,如果在指定时间内获得不到锁,则返回false。
针对上面的三个特定以及ReentrantLock具体的获得锁方法,编写测试代码如下:
测试主方法:
public class MainTest { public static void main(String[] args) throws InterruptedException { ReentrantLock lock = new ReentrantLock(); Thread threadA = new Thread(new ThreadA(lock)); threadA.setName("线程A"); Thread threadB = new Thread(new ThreadB(lock)); threadB.setName("线程B"); threadB.start(); Thread.sleep(1000); threadA.start(); } //测试线程B public class ThreadB implements Runnable{ private ReentrantLock lock; public ThreadB(ReentrantLock lock) { this.lock = lock; } public void run() { lock.lock(); try { System.out.println("B对象获得锁"); Thread.sleep(5000); }catch (Exception ex) { ex.printStackTrace(); }finally { lock.unlock(); } } } }
void lock(),lock方式是阻塞方式的获得锁,B线程获得锁后等待了5秒,在这个过程中A线程尝试获得锁,在B线程等待期间线程A一直处于阻塞状态,直到线程B释放锁后A线程才获得锁。
public class ThreadA implements Runnable{ private ReentrantLock lock; public ThreadA(ReentrantLock lock) { this.lock = lock; } public void run(){ lock.lock(); try { System.out.println("A对象获得锁"); }catch (Exception ex) { ex.printStackTrace(); }finally { lock.unlock(); } } } 指定结果: B对象获得锁 B对象等待5秒 A对象获得锁
boolean tryLock(),tryLock方式为立即获得锁,如果获得不到则返回false,B线程获得锁后等待了5秒,在这个等待过程中A线程尝试获得锁,结果锁一直被B线程拿着,所以A线程直接返回false,修改测试类A:
public class ThreadA implements Runnable{ private ReentrantLock lock; public ThreadA(ReentrantLock lock) { this.lock = lock; } public void run(){ if (lock.tryLock()){ try { System.out.println("A对象获得锁"); }catch (Exception ex) { ex.printStackTrace(); }finally { lock.unlock(); } } } } 指定结果: B对象获得锁 B对象等待5秒
void lockInterruptibly(),lockInterruptibly获得锁后,如果当前线程获得锁后,代码中进行了interrupt中断后,线程可以继续进行,不会抛出移除,修改测试类A,增加中断代码:
//测试线程A public class ThreadA implements Runnable{ private ReentrantLock lock; public ThreadA(ReentrantLock lock) { this.lock = lock; } public void run(){ try { lock.lockInterruptibly(); try { System.out.println("A对象开始中断"); Thread.currentThread().interrupt(); System.out.println("A对象结束中断"); }catch (Exception ex) { ex.printStackTrace(); }finally { System.out.println("A对象释放锁"); lock.unlock(); } } catch (InterruptedException e) { e.printStackTrace(); } } } 指定结果: B对象获得锁 A对象开始中断 A对象结束中断 A对象释放锁
boolean tryLock(long timeout, TimeUnit unit),tryLock方式为在一段时间内获得锁,如果获得不到则返回false,B线程获得锁后等待了5秒,在这个等待过程中A线程如果在一秒内获得锁,获得锁,则返回true,否则返回false:
public class ThreadA implements Runnable{ private ReentrantLock lock; public ThreadA(ReentrantLock lock) { this.lock = lock; } public void run(){ try { if (lock.tryLock(6, TimeUnit.SECONDS)){ try { System.out.println("A对象在6秒内获得锁"); }catch (Exception ex) { ex.printStackTrace(); }finally { lock.unlock(); } } } catch (InterruptedException e) { e.printStackTrace(); } } } 指定结果: B对象获得锁 B对象等待5秒 A对象在6秒内获得锁
以上是关于ReentrantLock说明的主要内容,如果未能解决你的问题,请参考以下文章
为什么JDK代码这样写?final ReentrantLock takeLock = this.takeLock