高并发编程之ReentrantLock工具类讲解
一、ReentrantLock介绍
①、ReentrantLock实现了Lock接口,加锁和解锁都需要显式写出,注意一定要在适当时候unlock。
②、可重入锁。可重入锁是指同一个线程可以多次获取同一把锁。也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞
③、可中断锁。可中断锁是指线程尝试获取锁的过程中,是否可以响应中断。synchronized是不可中断锁,而ReentrantLock则提供了中断功能。
④、公平锁与非公平锁。公平锁是指多个线程同时尝试获取同一把锁时,获取锁的顺序按照线程达到的顺序,而非公平锁则允许线程“插队”。synchronized是非公平锁,而ReentrantLock的默认实现是非公平锁,但是也可以设置为公平锁。
注意:使用重入锁进行加锁是一种显式操作,通过何时加锁与释放锁使重入锁对逻辑控制的灵活性远远大于synchronized关键字。同时,需要注意,有加锁就必须有释放锁,而且加锁与释放锁的分数要相同
二、ReentrantLock相对于synchronized的优势
①、ReentrantLock的优势在于它更灵活、更强大,除了常规的lock()、unlock()之外,还有lockInterruptibly()、tryLock()方法,支持中断、超时。
②、ReentrantLock默认使用非公平锁是基于性能考虑,公平锁为了保证线程规规矩矩地排队,需要增加阻塞和唤醒的时间开销。如果直接插队获取非公平锁,跳过了对队列的处理,速度会更快。
③、可以添加多个检控条件, 如果使用synchronized,则只能使用一个. 使用 reentrant locks 可以有多个wait()/notify() 队列. [译注:直接多new 几个ReentrantLock就可以了,不同的场景/条件用不同的ReentrantLock ]。
④、可以控制线程得到锁的顺序,也就是有公平锁(按照进入顺序得到资源),也可以不按照顺就像.synchronized 一样。
⑤、可以查看锁的状态, 锁是否被锁上了。
⑥可以查看当前有多少线程再等待锁。
三、Java代码示例
①、lock()方法:获取锁,如果锁不可用,出于线程调度目的,将禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态。
package chapter3.locks; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; /** * @author czd */ public class ReentrantLockTest { /** * 非公平锁,当ReentrantLock(true)时是公平锁,都不是绝对公平,只是相对公平 */ private static final ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { for(int i = 0; i < 2; i++){ new Thread(){ @Override public void run() { needLock(); } }.start(); } } public static void needLock(){ try { //不可被中断 lock.lock(); System.out.println(Thread.currentThread().getName()+">>>needLock()方法的效果与needLockLikeSyn()一样,但是速率比它快一点!"); TimeUnit.SECONDS.sleep(2); System.out.println("任务结束!"); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } /** * 这个方法实现的是利用synchronized关键字加锁 */ public static void needLockLikeSyn(){ synchronized (ReentrantLockTest.class){ try { TimeUnit.SECONDS.sleep(2); System.out.println(Thread.currentThread().getName()+">>>这个方法的效果与needLock()一样,但是速率比它慢一点!"); }catch (Exception e){ e.printStackTrace(); } } } }
输出结果
②、lockInterruptibly()方法:支持对锁获取的中断。
package chapter3.locks; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; /** * @author czd */ public class ReentrantLockTest { /** * 非公平锁,当ReentrantLock(true)时是公平锁,都不是绝对公平,只是相对公平 */ private static final ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { for(int i = 0; i < 2; i++){ new Thread(){ @Override public void run() { needLockInterruptibly(); } }.start(); } } public static void needLockInterruptibly(){ try { //当抢不到锁时,该线程允许被打断 lock.lockInterruptibly(); System.out.println(Thread.currentThread().getName()+">>>needLockInterruptibly()方法的效果与needLockLikeSyn()一样,但是速率比它快一点!"); TimeUnit.SECONDS.sleep(2); System.out.println("任务结束!"); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } /** * 这个方法实现的是利用synchronized关键字加锁 */ public static void needLockLikeSyn(){ synchronized (ReentrantLockTest.class){ try { TimeUnit.SECONDS.sleep(2); System.out.println(Thread.currentThread().getName()+">>>这个方法的效果与needLock()一样,但是速率比它慢一点!"); }catch (Exception e){ e.printStackTrace(); } } } }
输出结果
③、tryLock()方法:如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false。
package chapter3.locks; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; /** * @author czd */ public class ReentrantLockTest { /** * 非公平锁,当ReentrantLock(true)时是公平锁,都不是绝对公平,只是相对公平 */ private static final ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { for(int i = 0; i < 2; i++){ new Thread(){ @Override public void run() { needTryLock(); } }.start(); } } public static void needTryLock(){ if (lock.tryLock()){ try { System.out.println(Thread.currentThread().getName()+">>>needTryLock()方法的效果与needLockLikeSyn()一样,但是速率比它快一点!"); TimeUnit.SECONDS.sleep(2); System.out.println("任务结束!"); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } }else{ System.out.println(Thread.currentThread().getName() + ">>>没有获得锁!"); } } /** * 这个方法实现的是利用synchronized关键字加锁 */ public static void needLockLikeSyn(){ synchronized (ReentrantLockTest.class){ try { TimeUnit.SECONDS.sleep(2); System.out.println(Thread.currentThread().getName()+">>>这个方法的效果与needLock()一样,但是速率比它慢一点!"); }catch (Exception e){ e.prin 4000 tStackTrace(); } } } }
输出结果
④、tryLock(long time,TimeUnit unit)方法:如果锁在给定的等待时间内空闲,并且当前线程未被 中断,则获取锁。
package chapter3.locks; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; /** * @author czd */ public class ReentrantLockTest { /** * 非公平锁,当ReentrantLock(true)时是公平锁,都不是绝对公平,只是相对公平 */ private static final ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { for(int i = 0; i < 2; i++){ new Thread(){ @Override public void run() { try { needTryLock(2); }catch (InterruptedException e){ e.printStackTrace(); } } }.start(); } } public static void needTryLock(long seconds) throws InterruptedException{ if (lock.tryLock(seconds,TimeUnit.SECONDS)){ try { System.out.println(Thread.currentThread().getName()+">>>needTryLock()方法的效果与needLockLikeSyn()一样,但是速率比它快一点!"); TimeUnit.SECONDS.sleep(5); System.out.println("任务结束!"); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } }else{ System.out.println(Thread.currentThread().getName() + ">>>在"+seconds+"秒内没有获得锁!"); } } /** * 这个方法实现的是利用synchronized关键字加锁 */ public static void needLockLikeSyn(){ synchronized (ReentrantLockTest.class){ try { TimeUnit.SECONDS.sleep(2); System.out.println(Thread.currentThread().getName()+">>>这个方法的效果与needLock()一样,但是速率比它慢一点!"); }catch (Exception e){ e.printStackTrace(); } } } }
输出结果
- 高并发编程之ReentrantReadWriteLock工具类讲解
- Java并发编程之ReentrantLock学习
- 深入Java多线程和并发编程之ReentrantLock
- 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock
- 【Java并发编程】15、ReentrantLock实现原理深入探究
- Java 并发编程之ReentrantLock和synchronized锁
- Java并发编程之ReentrantLock源码分析
- Java 多线程并发编程之互斥锁 Reentrant Lock
- Android并发编程之如何使用ReentrantReadWriteLock替代synchronized来提高程序的效率
- 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock
- 并发编程学习总结(六) :java 显式锁ReentrantLock使用详解之测试锁与超时
- Java并发编程 ReentrantLock 源码分析
- Java 并发编程 --- 读写锁:ReentrantReadWriteLock
- 并发编程实践五:ReentrantLock
- java并发编程之:ReentrantLock实现原理与深入研究
- JAVA并发编程学习笔记之ReentrantLock (r)
- Java并发编程之ReentrantLock
- 【Java并发编程实战】—–“J.U.C”:ReentrantLock之一简介
- 并发编程学习总结(五) :java 显式锁ReentrantLock使用详解之条件对象(2)
- 高并发编程之Condition工具类讲解