当前位置: 首页 > 知识库问答 >
问题:

java多线程中“私有最终对象”锁定有什么用?

何涵育
2023-03-14

Java多线程中“私有最终对象”锁定有什么用?

就我的理解而言,我认为要使一个类成为线程安全的,我们要么使用内在锁定,要么将所有方法标记为同步的

例如,使用内在锁定的代码:

public class Counter{

 // Locks on the object's monitor
 public synchronized void changeValue() { 
   // ...
 }

}

我们可以用以下外在锁替换上面的代码:

public class Counter{
 private final Object lock = new Object(); // private final lock object

  public void changeValue() {
   synchronized (lock) { // Locks on the private Object
  // ...
       }
  }
}

是否建议使用上述外部锁而不是使用内部锁定使类作为线程安全?如果我的理解在这里有误,请纠正我?

共有3个答案

锺离穆冉
2023-03-14

该规则处理同步块中使用的监视器对象的类型。总结这篇文章,建议使用外部锁(称为私有锁对象习语)。

  1. 在无法更改的对象实例上拥有锁会使同步更加一致。当同步对象无法更改时,很难中断同步。
  2. 由于锁位于特定对象上,因此即使线程正在处理同步块,其他类资源也可用。这使得代码更健壮,更不容易受到死锁的影响。
边永贞
2023-03-14

下面的示例明确了何时使用,

public class Foo {
    // Locks on the object's monitor
    public synchronized void changeValue() {
        // ...
    }
    public static Foo changeState(String name) {
        // Manipulate on Foo 
        return obj;
    }
    public static void main(String[] args) throws InterruptedException {
        // Untrusted code
        String name = "test" ;
        Foo foo = Foo.changeState(name);
        if (foo == null) {
            throw new IllegalStateException();
        }
        synchronized (foo) {
            while (true) {
                // Indefinitely lock someObject
                Thread.sleep(Integer.MAX_VALUE);
            }
        }
    }
}
梁丘钊
2023-03-14

Oracle Secure编码标准包含您需要的所有信息。

基本上是为了防止这种情况:声明为同步的方法和在此引用上同步的块都使用对象的监视器(即其内部锁)。攻击者可以通过获取并无限期持有可访问类的内部锁来操纵系统以触发争用和死锁,从而导致拒绝服务 (DoS)。

 类似资料:
  • 问题内容: 在阅读有关同步的内容时,我遇到了“监视器模式”以封装可变状态。 以下是示例代码 } 用私有锁代替固有锁更好吗? 问题答案: 是的-这意味着您可以看到 所有可能获得该锁的代码 (不考虑反射的可能性)。 如果您锁定(这是我假设您通过“固有锁定”所指的),那么其他代码可以做到: 该代码可能与自己的代码相距很远,并且可能调用其他方法,这些方法又将监视器带走。在这里很容易陷入死锁领域,因为您不容

  • 本文向大家介绍Java类锁、对象锁、私有锁冲突测试,包括了Java类锁、对象锁、私有锁冲突测试的使用技巧和注意事项,需要的朋友参考一下 类锁和对象锁是否会冲突?对象锁和私有锁是否会冲突?通过实例来进行说明。 一、相关约定 为了明确后文的描述,先对本文涉及到的锁的相关定义作如下约定: 1. 类锁:在代码中的方法上加了static和synchronized的锁,或者synchronized(xxx.c

  • 问题内容: 锁定后总是会出现try / finally块,为什么? 为什么要尝试/最终阻止而不是简单地编写如下代码: 问题答案: 万一出了什么问题(抛出异常等),您无论如何都要确保释放了锁。这只是标准做法,即使在技术上在这种情况下也没有必要。

  • 问题内容: 我有一个Web应用程序,并且正在使用Oracle数据库,并且有一种基本上像这样的方法: 现在没有任何类型的同步,因此n个线程当然可以自由地访问此方法,当2个线程都进入此方法都进行检查并且当然还没有任何东西时,就会出现问题,然后它们都可以提交事务并创建一个重复的对象。 我不想在数据库中使用唯一的密钥标识符来解决此问题,因为我认为我不应该抓住它。 我也不能在提交之前进行检查,因为不仅要进行

  • 问题内容: 以下函数在其自己的线程中执行: 当执行到达该行时,将引发异常: 有谁知道如何锁定对象或函数以防止并发?我试图添加一个Lock对象: 和线 在功能开始时,但是没有用。 问题答案: 为了在一个对象上调用wait(),您必须在该对象上持有同步锁(尽管该锁实际上是在线程等待时释放的): 我必须承认,在这种情况下, 为什么 您要这样做让我感到困惑…

  • 我在这里读了一些关于创建不可变对象的书,我想知道,我有以下类: 这是Oracle建议创建不可变类的方式,但是,在C#中,你可以声明你的setter私有,Java如果我这样做,它仍然是不可变的吗? 实现私有setter而不是使私有变量为final并使用构造函数有什么错?