ReentrantLock是一种可重入的互斥锁,而且加锁是一种显式操做,对逻辑控制的灵活性远远大于synchronized关键字。重入锁是能够彻底替代synchronized。而且重入锁的性能是远高于synchronized的,可是jdk6.0开始,jdk对synchronized作了大量的优化,使得二者性能差距不大。另外,ReentrantLock可结合Condition、以及提供了中断响应、锁申请等待限时、公平锁等。java
ReentrantLock分为“公平锁”和“非公平锁”。它们的区别体如今获取锁的机制上是否公平。在“公平锁”的机制下,线程依次排队获取锁;而“非公平锁”在锁是可获取状态时,无论本身是否是在队列的开头都会获取锁。函数
运行以下代码,对比公平锁和非公平锁的运行结果性能
public static void main(String[] args) throws InterruptedException { Lock noFairReentrantLock = new ReentrantLock(); Lock fairReentrantLock = new ReentrantLock(true); Thread[] threads = new Thread[10]; for(int i=0;i<10;i++){ threads[i] = new Thread(()->{ System.out.println(Thread.currentThread().getName()+" [start]"); fairReentrantLock.lock();//也能够切换为非公平锁,观察运行结果 try { System.out.println(Thread.currentThread().getName()+" [得到锁]"); }finally { fairReentrantLock.unlock(); } }); } for(int i=0;i<5;i++){ threads[i].start(); } for(int i=0;i<5;i++){ threads[i].join(); } } }
对于synchronized块来讲,要么获取到锁执行,要么持续等待。而重入锁的中断响应功能就合理地避免了这样的状况。好比,一个正在等待获取锁的线程被“告知”无须继续等待下去,就能够中止工做了。优化
下面咱们看一个利用中断响应功能解决的一个死锁问题线程
public static void main(String[] args) throws InterruptedException { ReentrantLock lock1 = new ReentrantLock(); ReentrantLock lock2 = new ReentrantLock(); //线程t1和t2构成了死锁,此时咱们能够中断的方式解决死锁问题 Runnable runnable = ()->{ try { if(Thread.currentThread().getName().equals("t1")){ lock1.lockInterruptibly(); //在加锁的过程当中仍然能够相应中断 Thread.sleep(100); lock2.lockInterruptibly(); }else{ lock2.lockInterruptibly(); Thread.sleep(100); lock1.lockInterruptibly(); } } catch (InterruptedException e) { e.printStackTrace(); }finally { if (lock1.isHeldByCurrentThread()) lock1.unlock(); if (lock2.isHeldByCurrentThread()) lock2.unlock(); } }; Thread t1 = new Thread(runnable,"t1"); Thread t2 = new Thread(runnable,"t2"); t1.start();t2.start(); Thread.sleep(1000); //以中断的方式解决死锁问题 t2.interrupt(); }
可使用 tryLock()或者tryLock(long timeout, TimeUtil unit) 方法进行一次限时的锁等待。code
public static void main(String[] args) throws InterruptedException { ReentrantLock lock = new ReentrantLock(); Runnable runnable = ()->{ try { if (lock.tryLock(1, TimeUnit.SECONDS)) { // 等待1秒 Thread.sleep(2000); } else { System.err.println(Thread.currentThread().getName() + "获取锁失败!"); } } catch (Exception e) { if (lock.isHeldByCurrentThread()) lock.unlock(); } }; Thread t1 = new Thread(runnable,"t1"); Thread t2 = new Thread(runnable,"t2"); t1.start();t2.start(); }
配合关键字synchronized使用的方法如:await()、notify()、notifyAll(),一样配合ReentrantLock 使用的Conditon提供了如下方法:对象
public interface Condition { void await() throws InterruptedException; // 相似于Object.wait() void awaitUninterruptibly(); // 与await()相同,但不会再等待过程当中响应中断 long awaitNanos(long nanosTimeout) throws InterruptedException; boolean await(long time, TimeUnit unit) throws InterruptedException; boolean awaitUntil(Date deadline) throws InterruptedException; void signal(); // 相似于Obejct.notify() void signalAll(); }
ReentrantLock 配合 Condition的例子队列
public static void main(String[] args) throws InterruptedException { ReentrantLock lock = new ReentrantLock(true); Condition condition = lock.newCondition(); Thread t = new Thread(()->{ try { lock.lock(); System.err.println(Thread.currentThread().getName() + "-线程开始等待..."); condition.await(); System.err.println(Thread.currentThread().getName() + "-线程继续进行了"); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } }, "t1"); t.start(); Thread.sleep(1000); System.err.println("过了1秒后..."); lock.lock(); condition.signal(); // 调用该方法前须要获取到建立该对象的锁不然会产生java.lang.IllegalMonitorStateException异常 lock.unlock(); }
// 建立一个 ReentrantLock ,默认是“非公平锁”。 ReentrantLock() // 建立策略是fair的 ReentrantLock。fair为true表示是公平锁,fair为false表示是非公平锁。 ReentrantLock(boolean fair) // 查询当前线程保持此锁的次数。 int getHoldCount() // 返回目前拥有此锁的线程,若是此锁不被任何线程拥有,则返回 null。 protected Thread getOwner() // 返回一个 collection,它包含可能正等待获取此锁的线程。 protected Collection<Thread> getQueuedThreads() // 返回正等待获取此锁的线程估计数。 int getQueueLength() // 返回一个 collection,它包含可能正在等待与此锁相关给定条件的那些线程。 protected Collection<Thread> getWaitingThreads(Condition condition) // 返回等待与此锁相关的给定条件的线程估计数。 int getWaitQueueLength(Condition condition) // 查询给定线程是否正在等待获取此锁。 boolean hasQueuedThread(Thread thread) // 查询是否有些线程正在等待获取此锁。 boolean hasQueuedThreads() // 查询是否有些线程正在等待与此锁有关的给定条件。 boolean hasWaiters(Condition condition) // 若是是“公平锁”返回true,不然返回false。 boolean isFair() // 查询当前线程是否保持此锁。 boolean isHeldByCurrentThread() // 查询此锁是否由任意线程保持。 boolean isLocked() // 获取锁。 void lock() // 若是当前线程未被中断,则获取锁。 void lockInterruptibly() // 返回用来与此 Lock 实例一块儿使用的 Condition 实例。 Condition newCondition() // 仅在调用时锁未被另外一个线程保持的状况下,才获取该锁。 boolean tryLock() // 若是锁在给定等待时间内没有被另外一个线程保持,且当前线程未被中断,则获取该锁。 boolean tryLock(long timeout, TimeUnit unit) // 试图释放此锁。 void unlock()