深入理解 final 关键字在并发编程中的应用

42 阅读2分钟

  final 是 Java 中一个关键字,它可以用来修饰类、方法和变量,甚至还可以用来修饰局部变量和参数。

基础使用

  • 修饰类

  当一个类被声明为final时,它不能被其他类继承。比如StringL类就是是final类型

image.png

  • 修饰方法

  当一个方法被声明为final时,这个方法不能被子类重写。可以用于确保某些关键方法的行为不被改变。虽然不能重写,但是final方法是可以被重载的,这一点需要注意。

class Parent {
    final void display() {
        System.out.println("This is a final method.");
    }
}

class Child extends Parent {
    // void display() { // 编译错误,无法重写 final 方法
    //     System.out.println("Trying to override.");
    // }
    
    // 重载
    void display(String name) { System.out.println("This is a final method."+name); }
}

  当我们用private修饰方法时,都隐式地指定为final的

  • 修饰变量

  当一个变量被声明为final时,它的值在初始化后不能再被改变,成为了一个常量。

final int MAX_VALUE = 100;
// MAX_VALUE = 200; // 编译错误,无法修改 final 变量

多线程并发

  在并发编程中,多个线程可能会同时访问和修改同一数据。如果数据是可变的,可能会导致数据不一致的情况。

class SharedResource {


    private int param;

    private final int value;

    public SharedResource(int value) {
        this.value = value; // 在构造函数中初始化
        this.param=10;
    }

    public int getValue() {
        return value;
    }
    
      public int getParam() {
        return param;
    }
}

  上述对象在创建的时候,由于指令重排序我们有可能拿到一个未完全初始化的对象,那么该对象里面的普通变量的值可能就是各种数据类型的默认值,而不是实际的值。

  而被final修饰的变量,造器结束时,JVM会确保final字段的写操作对所有线程可见,这相当于在构造器结束时插入了一个内存屏障,防止了指令重排序带来的问题。

总结

  final关键字,它可以用来修饰类、方法、变量、局部变量和参数,确保了内存可见性、不可变性,防止重排序。