3 回答
TA贡献1865条经验 获得超7个赞
一个ReentrantLock的是非结构化的,不像synchronized结构-即你不需要使用块结构锁,甚至可以举行跨越方法的锁。一个例子:
private ReentrantLock lock;
public void foo() {
...
lock.lock();
...
}
public void bar() {
...
lock.unlock();
...
}
这样的流程不可能通过synchronized构造中的单个监视器来表示。
除此之外,还ReentrantLock支持锁定轮询和支持超时的可中断锁定等待。ReentrantLock它还支持可配置的公平性策略,从而允许更灵活的线程调度。
此类的构造函数接受一个可选的fairness参数。设置为set时true,在争用下,锁倾向于授予对等待时间最长的线程的访问。否则,此锁不能保证任何特定的访问顺序。与使用默认设置的程序相比,使用许多线程访问的公平锁的程序可能会显示较低的总体吞吐量(即,速度较慢;通常要慢得多),但获得锁的时间变化较小,并确保没有饥饿。但是请注意,锁的公平性不能保证线程调度的公平性。因此,使用公平锁的许多线程之一可能会连续多次获得它,而其他活动线程没有进行且当前未持有该锁。另请注意,未定时tryLock方法不遵循公平性设置。如果锁定可用,即使其他线程正在等待,它将成功。
ReentrantLock 可能还具有更高的可扩展性,在更高的竞争下表现更好。您可以在此处了解更多信息。
但是,此主张遭到了质疑;看到以下评论:
在可重入锁测试中,每次都会创建一个新锁,因此没有互斥锁,并且结果数据无效。另外,IBM链接不提供基础基准测试的源代码,因此无法描述测试是否正确进行。
什么时候应该使用ReentrantLocks?根据该developerWorks文章...
答案很简单-在您确实需要它提供的东西时使用它synchronized,例如定时锁等待,可中断锁等待,非块结构锁,多个条件变量或锁轮询。ReentrantLock它还具有可伸缩性的好处,如果您实际遇到竞争激烈的情况,则应使用它,但是请记住,绝大多数synchronized块几乎从未表现出任何竞争,更不用说竞争激烈了。我建议您进行同步开发,直到证明同步不足为止,而不是简单地假设“性能会更好”。ReentrantLock。请记住,这些是面向高级用户的高级工具。(并且,真正的高级用户倾向于使用他们能找到的最简单的工具,直到他们确信简单的工具是不合适的。)与往常一样,首先使其正确,然后再担心是否必须使其更快。
TA贡献1895条经验 获得超7个赞
ReentrantReadWriteLock是专用锁,而是synchronized(this)通用锁。它们相似但不完全相同。
您是对的,可以使用synchronized(this)代替,ReentrantReadWriteLock但并非总是如此。
如果您想更好地了解是什么让它ReentrantReadWriteLock特别有用,请查找有关生产者-消费者线程同步的一些信息。
通常,您可以记住,全方法同步和通用同步(使用synchronized关键字)可以在大多数应用程序中使用,而无需过多考虑同步的语义,但是如果您需要从代码中压缩性能,则可能需要探索其他更细粒度或专用的同步机制。
顺便说一句,使用synchronized(this)-以及通常使用公共类实例进行锁定-可能会出现问题,因为它会使您的代码面临潜在的死锁,因为其他人可能会试图在程序中的其他位置尝试锁定您的对象。
添加回答
举报