当前位置: 首页 > 面试题库 >

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

欧阳正卿
2023-03-14
问题内容

我试图了解是什么使并发锁如此重要,如果可以使用的话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;
}

问题答案:

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



 类似资料:
  • 问题内容: Angular对于构建单页应用程序非常有用。它基本上建立在当前范例上,在该范例中我们向不同的端点发出请求,以帮助我们创建更好的单页应用程序。 另一方面,我们拥有的Meteor似乎更加强大,特别是因为它们具有称为DDP的功能,该功能基本上允许双向数据流。看来Meteor是Angular的超集,并且显然是更好的选择。 尽管Angular确实提供了一些诸如测试和本地化之类的功能,但我只是不明

  • 我试图理解,如果可以使用,是什么让并发锁如此重要。在下面的伪代码中,我可以执行以下任一操作: 同步整个方法或同步脆弱区域(

  • 根据我的理解,有两个主要的Java类能够执行伪随机性活动:类和类。两者都生成伪随机数。但是,类生成加密安全的数字。 我唯一的解释是类比类运行得更快。这是真的吗?如果不是,那么为什么许多Java程序员更喜欢类而不是类呢?

  • 问题内容: 假设我们的应用程序只有一个线程。然后我们正在使用,这是什么问题? 我的意思是,如果可以通过同步处理多个线程,那么使用单线程有什么问题? 为什么要改用? 问题答案: 是线程安全的,这意味着它们具有同步的方法来控制访问,因此一次只有一个线程可以访问StringBuffer对象的同步代码。因此,在多个线程可能试图同时访问同一StringBuffer对象的多线程环境中,StringBuffer

  • 为什么要用 this? 如果对于那些老练的 JavaScript 开发者来说 this 机制都是如此的令人费解,那么有人会问为什么这种机制会有用?它带来的麻烦不是比好处多吗?在讲解 如何 有用之前,我们应当先来看看 为什么 有用。 让我们试着展示一下 this 的动机和用途: function identify() { return this.name.toUpperCase(); } f

  • 问题内容: 我将所有JS作为外部文件包括在内,这些文件在页面的底部加载。在这些文件中,我定义了几个这样的方法,我从ready事件中调用它们: 但是,当我删除ready函数并直接调用方法时,所有工作原理都相同,但是执行起来明显更快—在一个漂亮的基本文件上,几乎快了一秒钟!由于应该在此时加载文档(因为所有标记都在script标记之前),是否有充分的理由仍然使用ready事件? 问题答案: 好问题。 整