不变模式-使用不变模式后,所有实例的方法均不需要进行同步操作,保证了他们在多线程环境下的性能。

发布时间:2023年12月24日

在并行软件开发过程中,同步操作似乎是必不可少的。
当多线程对同一个对象进行读写操作时,为了保证对象数据的一致性
和正确性,有必要对对象进行同步,但是同步操作对系统性能有损耗。
为了尽可能地去除这些同步操作,提高并行程序性能可用使用一种
不可改变的对象,依赖对象的不可变性,可用确保其在没有同步操作的
多线程环境中依然保持内部状态的一致性和正确性。这就是不变模式。

不变模式天生就是多线程友好的,它的核心思想是,一个对象一旦被创建,
它的内部状态将永远不会发生改变。没有一个线程可用修改其内部状态
和数据。同时其内部状态也绝不会自行发生改变。基于这些特性,
对不变对象的多线程操作不需要进行同步控制。
?同时还需要注意,不变模式和只读属性是有一定的区别的,不变模式比
只读属性具有更强的一致性和不变性。对只读属性的对象而言,
对象本身不能被其他线程修改,但是对象自身的状态却可能自行修改。

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

因此,不变模式的主要使用场景需要满足以下两个条件。
1.当对象创建后,其内部状态和数据不再发生任何变化。
2.对象需要被共享,被多线程频繁访问。

在java语言中,不变模式的实现很简单。
为确保对象被创建后,不发生任何改变,并保证
不变模式正常工作,只需要注意以下四点即可。
1.去除setter方法及所有修改自身属性的方法。
2.将所有属性设置为私有,并用final标记,确保其不可修改。
3.确保没有子类可用重载修改它的行为。
4.有一个可用创建完整对象的构造函数。

package org.example;

import jdk.nashorn.internal.runtime.arrays.IntOrLongElements;

public final class Product {
    private final String no;
    private final String name;
    private final double price;

    public Product(String no,String name,double price){
        super();
        this.no = no;
        this.name = name;
        this.price = price;
    }
    public String getNo(){
        return no;
    }
    public String getName(){
        return name;
    }
    public double getPrice(){
        return price;
    }
}

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

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

使用不变模式后,所有实例的方法
均不需要进行同步操作,保证了他们在多线程环境下的性能。

文章来源:https://blog.csdn.net/wcg_jishuo/article/details/135186804
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。