Final 可重入锁 安全发布

无状态对象(既不包含任何域,也不包含任何其他类中域的引用)一定是线程安全的。

Final

fianl域是不能修改的(但如果final域所引用的对象是可变的,那么这些被引用的对象是可变的)

除非需要可变域,否则应将其声明位final域。 


初始化:

    final int i = 0;    //在声明时就初始常量的值(每个对象的fianl常量都为一个值)

    public class Test{  //声明时未初始化,如果常量不通过构造方法或块初始化会报错

        final int i;

        {
            i=1;    //不可以再在构造函数里初始化i的值,因为块已经把常量初始化了(每个对象的fianl常量都为一个值)
        }

        Test(){
            i=1;    //通过构造方法初始化(如果有参构造器,每个对象的fianl常量可以是不同值)
        }
    }

    public class Test{  //静态类中初始化(每个对象的fianl常量都为一个值)

        static final int i;

        static{
            i=1;
        }
    }

可重入锁:为了避免死锁

当一个线程获取对象锁,需要再次获取这个对象锁:

    1. 一个对象中有多个同步方法

    2. 子类重写父类同步方法:

        super不是指父类对象,而是一个引用,引用从父类继承来的方法。

        super.父类方法,通过super引用调用从父类继承来的方法,锁对象仍然是子类对象。


public class aaa{
    public static void main(String[] args) {
        ccc ccc = new ccc();
        ccc.dothing();
    }
}

class bbb{
    public void dothing(){
        System.out.println("父类:"+this.toString());
    }
}

class ccc extends bbb{
    @Override
    public void dothing() {
        super.dothing();
        System.out.println("super:"+super.toString());
        System.out.println("子类:"+this.toString());
    }
}

输出:
    父类:ccc@62043840
    super:ccc@62043840
    子类:ccc@62043840

安全发布

不安全发布(多线程问题):

    public Holder holder;

    public void init() {
        holder = new Holder(42);
    }

    由于可见性问题,其他线程看到的Holder对象可能处于不一致状态。


安全发布(保证可见性):

    静态初始化器中初始化对象引用(public static Holder holder = new Holder(24);):最简单,最安全

    将对象引用保存在volatile域或者AtomicReferance对象中

    对象引用保存在final域中

    对象引用保存在由锁保护的域中


安全发布容器:
    ConcurrentMap
    CopyOnWriteArrayList
    BlockingQueue


可变对象:
    不仅需要安全发布,并且必须是线程安全的。

    解决:
        线程封闭:ThreadLocal
        只读共享:CopyOnWriteArrayList 和 CopyOnWriteArraySet
        同步:synchronizer
        保护对象:AtomicReferance

猜你喜欢

转载自www.cnblogs.com/loveer/p/11741838.html