Java SE5的java.util.concurrent类库还包含有定义在java.util.concurrent.locks中的显式的互斥机制。Lock对象必须被显式地创建、锁定和释放。因此,它与内建的锁形式相比,代码缺乏优雅性。但是,对于解决某些类型的问题来说,它更加灵活。
![](https://i-blog.csdnimg.cn/blog_migrate/9df9a6bd2d2e2a4e06134fb78ccee7fe.png)
MutexEvenGenerator添加了一个被互斥调用的锁,使用lock()和unlock()方法在next()内部创建了临界资源。当你在使用Lock对象时,将这里所示的惯用法内部化是很重要的:紧接着对lock()的调用,你必须放置在finally子句中带有unlock()的try-finally语句中。注意,return语句必须在try子句中出现,以确保unlock不会过早发生,从而将数据暴露给第二个任务。(如果还没返回就解锁,可能其他线程访问并改变了值,此线程就会获取到被污染的数据了)
尽管try-finally所需的代码比synchronized关键字要多,但是这也代表了显式的Lock对象的优点之一。如果在使用synchronized关键字时,某些事物失败了,那么就会抛出一个异常。但是你没有机会去做任何清理工作,以维护系统使其处于良好状态。有了显式的Lock对象,你就可以使用finally子句将系统维护在正确的状态了。
大体上,当你使用synchronized关键字时,需要写的代码量更少,并且用户错误出现的可能性也会降低,因此通常只有在解决特殊问题时,才使用显式的Lock对象。例如,用synchronized关键字不能尝试着获取锁且最终获取锁会失败,或者尝试着获取锁一段时间,然后放弃它,要实现这些,你必须使用concurrent类库。
Lock优势:可以尝试获取锁,可以尝试获取锁一段时间,然后放弃。就是说,它可以尝试性地排队,排上一段时间。如果没有拿到锁,就会退出队伍。对应的方法是
tryLock。
显式是相对什么来说的?
是相对synchronized来说的,synchronized是如何对对象加锁的我们看不见,但是Lock对象的话就非常直观了,它有对应的方法可以调用,比如加锁就调用lock,解锁就调用unlock。所以相对synchronized关键字来说,Lock对象的锁操作是显式的。
未解决问题:synchronized难道就不能用try-catch了?清理工作指哪些,异常处理吗?