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

为什么内在锁对象不需要特殊处理(静态、最终、易失性)?

云浩然
2023-03-14

在这个内部锁的预言机示例中,监视器对象从未被声明为易失性,最终或与任何其他常规对象没有任何区别

public class MsLunch {
    private long c1 = 0;
    private long c2 = 0;
    private Object lock1 = new Object();
    private Object lock2 = new Object();

    public void inc1() {
        synchronized(lock1) {
            c1++;
        }
    }

    public void inc2() {
        synchronized(lock2) {
            c2++;
        }
    }
}

有很多关于易失性块和同步块的问题

  • 易失性字段和同步块,
  • java中易失性和同步的区别
  • 何时在java中的多线程中使用易失性与同步,
  • 你有没有在java中使用过易失性关键字

和不可变对象

  • 什么是不可变对象,
  • Java 中的不变性和同步
  • 不可变对象 java 并发)在多线程处理中。

顺便提一下,我理解声明一个对象为final和不可变性之间的微妙区别,为什么final-object可以被修改,为什么声明锁对象为final不会使它不可变。

然而,我们有著名的单例类惰性初始化模式,其中< code>volatile变量的使用是必不可少的。

public class SingletonDemo {
    private static volatile SingletonDemo instance;
    private SingletonDemo() { }

    public static SingletonDemo getInstance() {
        if (instance == null ) {
            synchronized (SingletonDemo.class) {
                if (instance == null) {
                    instance = new SingletonDemo();
                }
            }
        }

        return instance;
    }
}

在上面的代码示例中,它使用 Class 对象作为锁。

由于对于一个被多个线程访问的对象,您需要使用如上所述的某种机制来确保原子访问,为什么对于内部锁对象,不需要任何特殊处理?

共有3个答案

常永怡
2023-03-14

在这个关于内部锁和其他锁的oracle示例中,监视器对象从未声明为volatile、final或与其他常规对象没有任何区别。

那不是真的。见下文。

由于对于一个被多个线程访问的对象,您需要使用如上所述的某种机制来确保原子访问,为什么对于内部锁对象,不需要任何特殊处理?

它确实有特殊待遇。它是同步的。

张权
2023-03-14

它可能应该是最终的。但final并没有什么特别之处,它只在一种特殊情况下需要(将函数内声明的变量引用到匿名类中)。任何其他的case final都只是提醒程序员不要覆盖变量-您可以删除程序中final这个词的其他用法,它将完美地工作。你说得对,程序员可能会给它赋值,然后引发问题。但如果他不这样做,就没有问题了。因此,在创建final时继续使用它,但程序不需要编译它。

至于静态 - 取决于用例。是要监视类的所有实例,还是要独立监视每个实例?在第一种情况下,您在第二种情况下不使用静态。

不需要Volatile,因为对象实际上并没有被多个线程更改。这是完全不同的,是Java语言中比volatile更古老的一部分。没有必要使变量可变,因为您不会更改它,用于监视对象的内部数据结构已经知道它们需要是线程安全的(并且比volatilepromise更强大)。

燕俊明
2023-03-14

这些锁不需要特殊处理,因为MsLunch对象本身需要在被任何其他线程看到之前发布。

public class MyMain {
  public static void main(String... args) {
    MsLunch lunch = new MsLunch();
    // ...

这是线程安全的,因为局部变量(“午餐”)对多个线程不可见。

接下来,下面的类使本地引用对系统中的所有线程可见。当这种情况发生时,我们需要使用易失性volatile 关键字有效地创建了一个内存屏障,用于安全地发布对象。这包括在赋值之前进行的所有写入,包括在构造对象时在内部进行的写入。

C、 f.安全发布

public class MyMain {

  public static volatile MsLunch publicLunch;

  public static void main(String... args) {
    MsLunch lunch = new MsLunch();
    publicLunch = lunch;
    //...
  }
}
 类似资料:
  • 我正试图在Kotlin上重写我的android应用程序,在转换ContentProvider合同类时遇到了问题。所以我有一个简单的契约类(省略了内容类型和内容uri等默认内容): 如果我理解正确的话,在静态编程语言中,我们没有静态成员。相反,我们有“伴侣对象”。所以在将其转换为静态编程语言后,我有这样的代码: 但是当我试图访问像合同这样的字段时。联系人。姓名,我有错误:“姓名有私人访问”。更改可见

  • 问题内容: 我是一个相对较新的QA工程师,致力于学习Selenium(使用Java),并且我想使用页面对象为页面建模。 目前,我的页面对象类是静态变量(用于定位页面元素的对象)和静态方法(用于获取By对象并执行页面功能)的集合。这对我来说似乎是最简单的方法,因为我的方法不需要依赖任何实例变量,而只需依赖定位符。 我只是在测试代码中根据需要调用这些方法。 但是,我读到的有关页面对象的所有内容都涉及实

  • 这里我的问题是在关闭连接对象时,在以下情况下会出现什么问题。 > 假设没有发生异常,在try块中它会自动关闭连接对象。 如果发生某些异常,它将转到catch块,在那里它将自动关闭连接对象。 关闭finally块中的连接对象。 注意:请不要说最后块中关闭连接对象很好。我知道那个。如果我在try块中保持关闭连接,接球块是否有任何问题请解释。

  • 问题内容: 如果省略,则会看到错误“ 无法在用其他方法定义的内部类中引用非最终变量jtfContent ”。 为什么匿名内部类必须要求外部类实例变量为final才能访问它? 问题答案: 首先,让我们放松一下,请放下那把枪。 好。现在,语言坚持的原因是它作弊是为了让你的内部类函数可以访问他们渴望的局部变量。运行时复制本地执行上下文(以及其他适当的内容),因此它坚持要求你进行所有操作,final以使事

  • 不允许在接口中使用静态/最终方法的原因到底是什么?

  • 我正在读杰弗里·里克特的书“通过C#进行CLR”。它是从那里引用的: Finalize方法在GC确定为垃圾的对象的垃圾收集完成时调用。这意味着不能立即回收这些对象的内存,因为Finalize方法可能执行访问字段的代码。因为一个可终结的对象必须在集合中存活,所以它会被提升到另一个世代,从而迫使该对象比它应该存活的时间长得多