深入理解Java内置锁和显式锁(2)

使用内置锁时,对象本身既是一把锁又是一个条件队列;使用显式锁时,RenentrantLock的对象是锁,条件队列通过RenentrantLock.newCondition()方法获取,多次调用该方法可以得到多个条件队列。

一个使用显式锁的典型示例如下:

// 显式锁的使用示例 ReentrantLock lock = new ReentrantLock(); // 获取锁,这是跟synchronized关键字对应的用法。 lock.lock(); try{ // your code }finally{ lock.unlock(); } // 可定时,超过指定时间为得到锁就放弃 try { lock.tryLock(10, TimeUnit.SECONDS); try { // your code }finally { lock.unlock(); } } catch (InterruptedException e1) { // exception handling } // 可中断,等待获取锁的过程中线程线程可被中断 try { lock.lockInterruptibly(); try { // your code }finally { lock.unlock(); } } catch (InterruptedException e) { // exception handling } // 多个等待队列,具体参考[ArrayBlockingQueue](https://github.com/CarpenterLee/JCRecipes/blob/master/markdown/ArrayBlockingQueue.md) /** Condition for waiting takes */ private final Condition notEmpty = lock.newCondition(); /** Condition for waiting puts */ private final Condition notFull = lock.newCondition();

注意,上述代码将unlock()放在finally块里,这么做是必需的。显式锁不像内置锁那样会自动释放,使用显式锁一定要在finally块中手动释放,如果获取锁后由于异常的原因没有释放锁,那么这把锁将永远得不到释放!将unlock()放在finally块中,保证无论发生什么都能够正常释放。

结论

内置锁能够解决大部分需要同步的场景,只有在需要额外灵活性是才需要考虑显式锁,比如可定时、可中断、多等待队列等特性。

显式锁虽然灵活,但是需要显式的申请和释放,并且释放一定要放到finally块中,否则可能会因为异常导致锁永远无法释放!这是显式锁最明显的缺点。

综上,当需要同步时请优先考虑更安全的更易用的隐式锁。

参考文献

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/4f68ec1fe9bcef82781bc7e698dfdcdb.html