参考文献:https://www.cnblogs.com/cloudblogs/p/6440160.html
由于Lock是由JDK实现的,所以不像synchronize锁的获取和释放都是由JVM控制的,Lock的获取和释放都需要手动进行,并且在发生异常时,不会自动释放锁。因此一般来说,使用Lock必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生。
1、lock() 获取锁与释放锁 ,如果锁已被其他线程获取,则进行等待。
1 Lock lock = ...; lock.lock(); 2 try{ 3 //处理任务 4 }catch(Exception ex){ 5 }finally{ 6 lock.unlock(); //释放锁 7 }
2、tryLock() 获取锁时有返回值可以得知获取锁操作是否成功
1 Lock lock = ...; 2 if(lock.tryLock()) { 3 try{ 4 //处理任务 5 }catch(Exception ex){ 6 }finally{ 7 lock.unlock(); //释放锁 8 } 9 }else { 10 //如果不能获取锁,则直接做其他事情 11 }
如果获取成功则返回True,如果锁被其他线程占用则返回FALSE,该方法会立即返回结果,不会让线程一直处于等待状态。
3、tryLock(long time,TimeUnit unit) 与tryLock() 类似,但是与tryLock立即返回结果不同,该方法在拿不到锁的情况下回等待time时间,如果在限定时间内还是拿不到锁就返回FALSE,如果在一开始或者等待时间内拿到锁则返回TRUE。
4、lockInterruptibly()
通过这个方法尝试获取锁时,如果线程正在等待获取锁,则该线程可以响应Thread.interrupt()中断。synchronize对于没有获得锁处于等待状态的线程无法响应中断。
1 public void method() throws InterruptedException { 2 lock.lockInterruptibly(); 3 try { //..... } 4 finally { lock.unlock(); } 5 }
lockInterruptibly方法必须放在try块中或者在调用lockInterruptibly的方法外声明抛出InterruptedException,推荐使用后者。
5、readWriteLock()
该锁提升了读操作的效率,不过要注意的是,如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁。如果有一个线程已经占用了写锁,则此时其他线程如果申请写锁或者读锁,则申请的线程也会一直等待释放写锁。
ReentrantLock lock = new ReentrantLock(true); ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);