[Concurrent programming - foundation] (d) secure distribution target

First, release and overflow

1.1, released objects

       Is an object that can be used by code outside the current range.

1.2, the object overflows

       A false release. When an object has not been constructed, it has been seen by other threads.

Second, the general release of unsafe objects

2.1, privatization array is modified by returning the value directly after get

  • The following code is by publicpublishing a domain class access level, any external threads in the class can access these domains
  • We can not guarantee that other threads will not modify this field, so that the value of the error private domain (below the code on the private domain has been modified)
package com.tangxz._5.publish;

import com.tangxz.annoations.NotThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;

/**
 * @Info: 发布对象
 * @Author: 唐小尊
 * @Date: 2019/12/27  10:26
 */
@Slf4j
@NotThreadSafe
public class UnsafePublish {
    private String[] states = {"a","b","c"};
    private String x = "x";

    public String[] getStates(){
        return states;
    }
    public String getX(){
        return x;
    }

    public static void main(String[] args) {
        UnsafePublish unsafePublish = new UnsafePublish();
        log.info("{}", Arrays.toString(unsafePublish.getStates()));
        unsafePublish.getStates()[0]="d";
        log.info("{}", Arrays.toString(unsafePublish.getStates()));
    }
}
/*输出:11:03:11.274 [main] INFO com.tangxz._5.publish.UnsafePublish - [a, b, c]
11:03:11.279 [main] INFO com.tangxz._5.publish.UnsafePublish - [d, b, c]*/

2.2, this introduction overflow

  • It can not be released before the completion of construction objects, this method can be avoided
  • This instance of inner class which contains a reference to the private domain object instance of the package, will be released before the object was not properly constructed, there may be unsafe factors in it, will lead to this reference overflow during construction error.
  • This code starts the configuration of a thread function in the process. Whether implicit or explicit start to start, this will cause an overflow in this reference. Before the new thread will always belong complete object construction have already seen it.
  • So to create a thread in the constructor, do not start it, but should start using a proprietary method to initialize or start a thread of unity
  • In fact, here we can use private constructors and factory methods to complete the objects to create and register a listener, etc., so as to avoid mistakes
    ---------------------- -------------------
  • If not object causes the release of two errors:
    Unexpected (1) Published thread any thread can see expired values are published objects
    (2) seen threads of the thread is published references is the latest, but is state publication object is expired
package com.tangxz._5.publish;

import com.tangxz.annoations.NotRecommend;
import com.tangxz.annoations.NotThreadSafe;
import lombok.extern.slf4j.Slf4j;

/**
 * @Info: this引入溢出
 * @Author: 唐小尊
 * @Date: 2019/12/27  10:31
 */
@Slf4j
@NotThreadSafe
@NotRecommend
public class Escape {
    private int thisCanBeEscape = 0;
    public Escape(){
        new InnerClass();
    }
    private class InnerClass{
        public InnerClass(){
            //this引入溢出
            //在对象完成构造之前不能让它发布
            log.info("{}",Escape.this.thisCanBeEscape);
        }
    }

    public static void main(String[] args) {
        new Escape();
    }
}
/*输出:11:22:14.381 [main] INFO com.tangxz._5.publish.Escape - 0*/

2.3, a thread-safe singleton

2.3.1 ordinary lazy mode (non-thread-safe)

       The singleton instance when the first use initialization, non-thread-safe

public class SingletonExample1 {
    //私有构造函数
    private SingletonExample1(){
    }
    //单例对象
    private static SingletonExample1 instance = null;
    //静态的工厂方法获取一个单例对象
    //多线程会出现问题,getInstance方法 + synchronized之后就变得安全了,但是会变得慢
    public static SingletonExample1 getInstance(){
        if (instance==null){
            instance = new SingletonExample1();
        }
        return instance;
    }
}
2.3.2 ordinary hungry man mode (thread-safe)

       The singleton instance of the class is loaded at the time of creation, thread-safe

public class SingletonExample2 {
    //私有构造函数
    private SingletonExample2() {
    }
    //单例对象
    private static SingletonExample2 instance = new SingletonExample2();
    
    public static SingletonExample2 getInstance() {
        return instance;
    }
}
2.3.3, lazy mode (non-thread-safe) (dual achieve synchronization lock)

       Initialization process has not been executed, direct return , because when executed to 2 when he has been the object, the object is not empty

public class SingletonExample3 {
    //私有构造函数
    private SingletonExample3() {
    }
    //1、memory = allocate() 分配对象内存空间
    //2、ctorInstance() 初始化对象
    //3、instance = memory 设置instance指向刚分配的内存
    //可能会出现指令重排的情况

    //JVM和CPU优化,发生了指令重排
    //1、memory = allocate() 分配对象内存空间
    //3、instance = memory 设置instance指向刚分配的内存
    //2、ctorInstance() 初始化对象

    //还没执行完初始化过程,就直接返回,因为当执行到2的时候就已经有了对象,对象就不为空
    //单例对象
    private static SingletonExample3 instance = null;
    //静态的工厂方法获取一个单例对象
    public static SingletonExample3 getInstance() {
        if (instance == null) {//双重检测机制          // B
            synchronized (SingletonExample2.class) {   //同步锁
                if (instance == null) {
                    instance = new SingletonExample3();// A - 3
                }
            }
        }
        return instance;
    }
2.3.4, lazy mode (thread-safe) volatile + dual detection mechanism

       Lazy mode, volatile+双重检测机制prohibition instruction reordering

public class SingletonExample5 {
    //私有构造函数
    private SingletonExample5() {
    }

    //单例对象  volatile+双重检测机制->不会发生指令重排
    private static volatile SingletonExample5 instance = null;

    //静态的工厂方法获取一个单例对象
    public static SingletonExample5 getInstance() {
        if (instance == null) {//双重检测机制          // B
            synchronized (SingletonExample2.class) {   //同步锁
                if (instance == null) {
                    instance = new SingletonExample5();// A - 3
                }
            }
        }
        return instance;
    }
}
2.3.5 execution order static fields and static code block

       Execution sequence static fields and static code block according to a position in the document. Static field and execution order of the static code block is performed according to the order of the Java file, occurring from top to bottom

//私有构造函数
    private SingletonExample6() {

    }

    //单例对象
    private static SingletonExample6 instance = null;
	//先执行
    static {
        instance = new SingletonExample6();
    }

    //后执行
    public static SingletonExample6 getInstance() {
        return instance;
    }

    public static void main(String[] args) {
        System.out.println(getInstance().hashCode());
        System.out.println(getInstance().hashCode());
    }
2.3.6 enumeration mode single-mode embodiment (high safety)
package com.tangxz._5.singleton;

import com.tangxz.annoations.Recommend;
import com.tangxz.annoations.ThreadSafe;

/**
 * @Info: 枚举实现实例化最安全,枚举模式最安全
 * @Author: 唐小尊
 * @Date: 2019/12/27  10:38
 */
@ThreadSafe
@Recommend
public class SingletonExample7 {
    //私有构造函数
    private SingletonExample7() {

    }
    public static SingletonExample7 getInstance() {
        return Singleton.INSTANCE.getInstance();
    }
    private enum  Singleton{
        INSTANCE;
        private SingletonExample7 singleton;
        //JVM保证这个方法绝对只调用一次
        Singleton(){
            singleton = new SingletonExample7();
        }
        public SingletonExample7 getInstance(){
            return singleton;
        }
    }
    public static void main(String[] args) {
        System.out.println(getInstance().hashCode());
        System.out.println(getInstance().hashCode());
    }
}

Third, secure publishing objects

3.1, secure the release of the object

  • Static initialization function to initialize an object reference
  • Save to the application object volatiletype field or AtomicReferenceobject
  • The object reference saved to a properly constructed object type field final
  • The object reference is saved to a domain protected by a lock

3.2, and operating specifications security code

  • Proxy mode using lazy mode volatile+双重检测机制implemented disable command rearrangement . To prevent a single case of multi-threaded mode, the object may appear just given memory space is directly returned.
  • Execution sequence static fields and static code block is based on the location in the document to the
  • Enumeration mode to achieve Singleton pattern is the most secure
发布了20 篇原创文章 · 获赞 1 · 访问量 563

Guess you like

Origin blog.csdn.net/weixin_42295814/article/details/103781116