Programmers: How concurrent shared variables to ensure safe and do not lock? !

This blog cat Uncle blog , reproduced, please state the source

Read this article about "15 minutes"

Fitness crowd read: Java Intermediate

Study notes, two days of rest (in fact, doing a simulation project combat period), and occasionally think about what they should do, is really meaningful to themselves or society do?

image
Photo on Visual hunt

Speak your answer

emmm, more than one answer, today introduce a straightforward

Reading the question: how do we guarantee thread-safe shared variable access, while avoiding the overhead introduced lock to generate it

In a concurrent environment, a subject that can easily be shared by multiple threads, then for data consistency is required

Although you can use explicit locks or CAS operation, but it will also bring some of the context switch overhead, etc.

To give an example of the current issues now

/**
 * @ClassName Cup
 * @Description 杯子 非线程安全
 * @Author MySelf
 * @Date 2019/9/25 21:28
 * @Version 1.0
 **/
public class Cup {

    //直径
    private double diameter;

    //高度
    private double height;

    public double getDiameter() {
        return diameter;
    }

    public double getHeight() {
        return height;
    }

    //非原子操作
    public void setCup(double diameter,double height){
        this.diameter = diameter;
        this.height = height;
    }
}
复制代码

The code above, we should be able to see non-thread-safe right (if you can not see, turn on an article under review)

Because when we assigned a diameter of setCup operation, another thread might have started reading his height, then it will be thread-safety issues.

So without the use of locks, how can you do?

Good to see chant down, and almost time to brush circle of friends, suddenly understand

Immutable objects

Yes, today said that the way to speak Cup becomes immutable objects!

Immutable objects: an object once it is created, its external visible status remains unchanged (similar String, Integer)

Then the above Cup need to how to modify it?

/**
 * @ClassName Cup
 * @Description 不可变对象,线程安全
 * @Author MySelf
 * @Date 2019/9/25 21:32
 * @Version 1.0
 **/
public final class Cup {

    private final double diameter;

    private final double height;

    public Cup(double diameter,double height){
        this.diameter = diameter;
        this.height = height;
    }

}
复制代码

This time not Jiuhaola never changed

Wait, I want to how to modify Cup ah? Even concurrent operation, my business may also need to modify this Cup ah

Let's adjust the field of view, modify the properties == replacement Cup instance Cup

Suppose we are a cup mold factory, have generated the most recent net red cup, but because of the impression that the Internet trend, and occasionally need a small change our this cup parameters, stopping production will lose money, so the code in the mold of the adapter on five lines They attribute the cup can be replaced in the case of immutable objects

/**
 * @ClassName MoldAdapter
 * @Description 模具适配器
 * @Author MySelf
 * @Date 2019/9/25 21:35
 * @Version 1.0
 **/
public class MoldAdapter {
    
    private Map<String,Cup> cupMap = new ConcurrentHashMap<String, Cup>();

    public void updateCup(String version,Cup newCup){
        cupMap.put(version, newCup);
    }

}
复制代码

ConcurrentHashMap involved here inside the lock, the cup and Demo new, replacement is not related, the process does not involve the lock

Perhaps with a few vague talk about Crane Machine Case?

Remember the ruin of my youth crane machines do?

I remember a long time ago, when his wife was still bubble, took her to play with dolls, you will be able to boast that she wanted to catch that one, the results ?????

image

It's called 50

Now it's our turn to stand up their own masters, and hum

Suppose we are the head of a doll Area machines, crane machines each have their corresponding machine number, pay two-dimensional code url, robotic frequency (right, non-professional mechanical workers, is here to assume that this is to make money focus), we assume that the shorts are a youth addicted to money, such as life, every night liquidation proceeds once the list.

During the recent National Day coincides with the number of visitors coming up ????

Insert, hereby cat [Java] said public number in advance I wish the 70th anniversary of the prosperity, peace and prosperity!

Want to make money ideas, Soso has jumped to the chest

So good means that the robot crane machines on the frequency

I need to modify the properties of the targeted part of the crane machine, though, I started to have a relationship map of coding machine with dolls

I will not become the object of introducing ideas into their business to make money to go

First, crane machines like object that becomes immutable objects

/**
 * @ClassName DollMachineInfo
 * @Description 娃娃机不可变对象
 * @Author MySelf
 * @Date 2019/9/25 21:51
 * @Version 1.0
 **/
public final class DollMachineInfo {

    //编号
    private final String number;

    //支付二维码url
    private final String url;

    //机械手频率
    private final int frequency;

    public DollMachineInfo(String number,String url,int frequency){
        this.number = number;
        this.url = url;
        this.frequency = frequency;
    }

    public DollMachineInfo(DollMachineInfo dollMachineInfoType){
        this.number = dollMachineInfoType.number;
        this.url = dollMachineInfoType.url;
        this.frequency = dollMachineInfoType.frequency;
    }

    public String getNumber() {
        return number;
    }

    public String getUrl() {
        return url;
    }

    public int getFrequency() {
        return frequency;
    }
}
复制代码

This time I need to modify the encoding machine and doll-relational mapping table, so the table also need to be immutable, he needs the support I get relational mapping table, and the need to replace the latest relational mapping content

/**
 * @ClassName MachineRouter
 * @Description 机器信息表
 * @Author MySelf
 * @Date 2019/9/25 21:57
 * @Version 1.0
 **/
public final class MachineRouter {
    //保证其在并发环境的内存可见性
    private static volatile MachineRouter instance = new MachineRouter();
    //code与机器之间的映射关系
    private final Map<String,DollMachineInfo> routeMap;

    // 2、存储不可变量routeMap
    public MachineRouter(){
        //将数据库表中的数据加载到内存,存为Map
        this.routeMap = MachineRouter.setRouteFromeDB();
    }

    // 3、从db将数据存入Map
    private static Map<String, DollMachineInfo> setRouteFromeDB(){
        Map<String, DollMachineInfo> map = new HashMap<String, DollMachineInfo>();
        //DB 代码
        return map;
    }

    // 1、初始化实例
    public static MachineRouter getInstance(){
        return instance;
    }

    /**
     * 根据code获取对应的机器信息
     * @param code 对应编码
     * @return 机器信息
     */
    public DollMachineInfo getMacheine(String code){
        return routeMap.get(code);
    }

    /**
     * 修改当前MachineRouter实例
     * @param newInstance 新的实例
     */
    public static void setInstance(MachineRouter newInstance){
        instance = newInstance;
    }


    private static Map<String, DollMachineInfo> deepCopy(Map<String,DollMachineInfo> d){
        Map<String, DollMachineInfo> result = new HashMap<String, DollMachineInfo>();
        for (String key : d.keySet()){
            result.put(key, new DollMachineInfo(d.get(key)));
        }
        return result;
    }


    public Map<String, DollMachineInfo> getRouteMap() {
        //防御性复制
        return Collections.unmodifiableMap(deepCopy(routeMap));
    }
}
复制代码

The next step is to add concurrent business update code

/**
 * @ClassName Worker
 * @Description 通讯对接类
 * @Author MySelf
 * @Date 2019/9/25 22:13
 * @Version 1.0
 **/
public class Worker extends Thread {

    @Override
    public void run(){
        boolean isRouterModification = false;
        String updateMachineInfo = null;
        while (true){
            //其余业务代码
            /**
             * 在通讯的Socket信息中解析,并更新数据表信息,再重置MachineRouter实例
             */
            if (isRouterModification){
                if ("DollMachineInfo".equals(updateMachineInfo)){
                    MachineRouter.setInstance(new MachineRouter());
                }
            }
            //其余业务代码
        }
    }

}
复制代码

Knock blackboard notes

Case finished, there is a basic concept, then say a jargon

It is an immutable object model, Immutable Object

Strictly speaking, an immutable object what conditions need to be met:

  • 1, the class itself fianl: prevent subclasses modify the definition of behavior
  • 2, all fields with fianl modification: There can be initialized in multithreaded been modified to ensure safe JMM field of the referenced object
  • 3, when the object is created, this keyword is not given to other classes
  • 4, if the other cited state of the variable objects (arrays, collections), must be private, not exposed outside, it is necessary to return the field, the defensive replication (Defensive Copy)

Immutable Object mode has two important things you should know about the same

ImmutableObject: responsible for storing a set of immutable state

  • getState *: returns the associated variable value ImmutableObject maintained, the value obtained by the argument to the constructor instantiation
  • getStateSnapshot: returns an array of state snapshots ImmutableObject maintenance

Manipulator: Change ImmutableObject maintenance, and when your needs change, you are involved in generating a new instance of ImmutableObject

  • changeStateTo: ImmutableObject value generating new instances according to the new state

A typical interaction scenarios

  • 1, respective states get the current value ImmutableObject
  • 2, call changeStateTo method to update the application state Manipulator
  • 3, changeStateTo create a new instance of ImmutableObject to reflect the new state, and returns
  • 4, get a snapshot of the state of New ImmutableObject

What a scene for use

Yes, he did meet the requirements of our title, but any kind of design has its appropriate scene mode

Generally more suitable:

  • The object does not change frequently (doll machine case)
  • Simultaneously writes the data set to ensure atomicity (Case cup)
  • Use an object as HashMap of key (note the object HashCode)

Points to note:

  • Object change frequently: Can cause CPU consumption, GC will be a burden
  • Defensive replication: avoiding external code changes its internal state

Professional Case

Traverse the set in a multithreaded environment is often introduced into the lock, to prevent traversal of the internal structure of the collection is changed

java.util.concurrent.CopyOnWriteArrayList on the use of ImmutableObject mode

Of course, we need the scene, traversing more frequently than they are modified in a scene

Maintain its internal array variable is used to store a collection, when you add an element, it will generate a new array, copy the set of elements to the new array, and the last element to add elements, and copied to the new array array, i.e., the array may be equivalent to a reference array ImmutableObject, note is an equivalent

Therefore, when traversing a CopyOnWriteArrayList, generates a direct example of an array Iterator example, without locking

Epilogue

Because the final CopyOnWriteArrayList I do not have a serious look at the source code, so do not start speaking meticulous, mainly we can understand the immutable object model, it is best to write out a Demo, to hope that we can use this idea in a production environment, writing poor, forgive me.

I MySelf, still adhere to the relevant knowledge and learning technology product manager, I hope this can bring you new knowledge.

Public number: Java Cat said.

Learning exchange group: 728 698 035

Now architecture (code farmers) and business technology consultant, uninhibited mediocre, love open source, life and unscheduled dry-talk program.

Image Text

Guess you like

Origin juejin.im/post/5d8c10e8e51d45783e4b673e