为了账号安全,请及时绑定邮箱和手机立即绑定

如果可以使用同步的(this),为什么还要使用ReentrantLock?

如果可以使用同步的(this),为什么还要使用ReentrantLock?

吃鸡游戏 2019-10-04 14:21:28
我试图了解是什么使并发锁如此重要,如果可以使用的话synchronized (this)。在下面的虚拟代码中,我可以执行以下任一操作:同步了整个方法或同步了易受攻击的区域(synchronized(this){...})或使用ReentrantLock锁定易受攻击的代码区域。码:    private final ReentrantLock lock = new ReentrantLock();     private static List<Integer> ints;    public Integer getResult(String name) {         .        .        .        lock.lock();        try {            if (ints.size()==3) {                ints=null;                return -9;            }               for (int x=0; x<ints.size(); x++) {                System.out.println("["+name+"] "+x+"/"+ints.size()+". values >>>>"+ints.get(x));            }        } finally {            lock.unlock();        }         return random;}
查看完整描述

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。请记住,这些是面向高级用户的高级工具。(并且,真正的高级用户倾向于使用他们能找到的最简单的工具,直到他们确信简单的工具是不合适的。)与往常一样,首先使其正确,然后再担心是否必须使其更快。


查看完整回答
反对 回复 2019-10-04
?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

ReentrantReadWriteLock是专用锁,而是synchronized(this)通用锁。它们相似但不完全相同。


您是对的,可以使用synchronized(this)代替,ReentrantReadWriteLock但并非总是如此。


如果您想更好地了解是什么让它ReentrantReadWriteLock特别有用,请查找有关生产者-消费者线程同步的一些信息。


通常,您可以记住,全方法同步和通用同步(使用synchronized关键字)可以在大多数应用程序中使用,而无需过多考虑同步的语义,但是如果您需要从代码中压缩性能,则可能需要探索其他更细粒度或专用的同步机制。


顺便说一句,使用synchronized(this)-以及通常使用公共类实例进行锁定-可能会出现问题,因为它会使您的代码面临潜在的死锁,因为其他人可能会试图在程序中的其他位置尝试锁定您的对象。


查看完整回答
反对 回复 2019-10-04
  • 3 回答
  • 0 关注
  • 684 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信