文章目录

  • 一、不变模式的概念
  • 二、不变模式的使用场景与特点
  • 三、Java中对不变模式的应用


一、不变模式的概念

在并行软件开发过程中,同步操作似乎是必不可少的。当多线程对同一个对象进行读写操作时,为了保证对象数据的一致性和正确性,有必要对对象进行同步,但是同步操作对系统性能有损耗。

为了尽可能地去除这些同步操作,提高并行程序性能可以使用一种不可改变的对象,依靠对象的不变性,可以确保其在没有同步操作的多线程环境中依然保持内部状态的一致性和正确性。这就是不变模式。

不变模式天生就是多线程友好的,它的核心思想是:一个对象一旦被创建,它的内部状态将永远不会发生改变。没有一个线程可以修改其内部状态和数据,同时其内部状态也绝不会自行发生改变。基于这些特性,对不变对象的多线程操作不需要进行同步控制。

要注意,不变模式和只读属性是有一定的区别的。不变模式比只读属性具有更强的一致性和不变性。对只读属性的对象而言,对象本身不能被其他线程修改,但是对象的自身状态却可能自行修改。比如,一个对象的存活时间(对象创建时间和当前时间的时间差)是只读的,任何一个第三方线程都不能修改这个属性,但是这是一个可变的属性,因为随着时间的推移,存活时间时刻都在发生变化。而不变模式则要求,无论出于什么原因对象自创建后,其内部状态和数据保持绝对的稳定。

二、不变模式的使用场景与特点

根据上面概念,可知不变模式的主要使用场景需要满足以下两个条件:

  • 当对象创建后,其内部状态和数据不再发生任何变化。
  • 对象需要被共享,被多线程频繁访问。

在Java语言中,不变模式的实现很简单。为确保对象被创建后,不发生任何改变,并保证不变模式正常工作,只需要注意以下四点即可:

  • 去除setter方法及所有修改自身属性的方法。
  • 将所有属性设置为私有,并用final标记,确保其不可修改。
  • 确保没有子类可以重载修改它的行为。
  • 有一个可以创建完整对象的构造函数。

以下代码实现了一个不变的产品对象,它拥有序列号、名称和价格三个属性。

// final 确保无子类
public final class Product {

    //  私有属性,不会被其他对象获取
    //  final保证属性不会被两次赋值
    private final String no;
    private final String name;
    private final String price;

    // 在创建对象时,必须指定数据,因为创建之后,无法进行修改
    public Product(String no, String name, String price) {
        super();
        this.no = no;
        this.name = name;
        this.price = price;
    }

    public String getNo() {
        return no;
    }

    public String getName() {
        return name;
    }

    public String getPrice() {
        return price;
    }
}

在不变模式的实现中,final关键字起到了重要的作用。对属性的final定义确保所有数据只能在对象被构造时赋值1次。之后,就永远不发生改变。而对class的final确保了类不会有子类。根据里氏代换原则,子类可以完全替代父类。如果父类是不变的,那么子类也必须是不变的,但实际上我们无法约束这点,为了防止子类做出一些意外的行为,这里干脆把子类都禁用了。

三、Java中对不变模式的应用

在JDK中,不变模式的应用非常广泛。其中,最为典型的就是java.lang.String类。此外,所有的元数据类、包装类都是使用不变模式实现的。主要的不变模式类型如下。

java.lang.String
java.lang.Boolean
java.lang.Byte
java.lang.Character
java.lang.Double
java.lang.Float
java.lang.Integer
java.lang.Long
java.lang.Short

由于基本数据类型和String类型在实际的软件开发中应用极其广泛,使用不变模式后,所有实例的方法均不需要进行同步操作,保证了它们在多线程环境下的性能。

注意:不变模式通过回避问题而不是解决问题的态度来处理多线程并发访问控制,不变对象是不需要进行同步操作的。由于并发同步会对性能产生不良的影响,因此,在需求允许的情况下,不变模式可以提高系统的并发性能和并发量。