Collections insecurity Set

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/longgeqiaojie304/article/details/89819422

Manufacturers face questions: We know that Set is not thread-safe, please write an insecure coding case and gives the solution?

1, Set thread insecurity problems

import java.util.HashSet;

import java.util.Set;

java.util.UUID import;

 

public class ContainerNotSafeDemoTwo {

    public static void main(String[] args) {

        Set<String> set = new HashSet<>();

        for (int i = 0; i < 30; i++) {

            new Thread(() -> {

                set.add(UUID.randomUUID().toString());

                System.out.println(set.toString());

            }, "T1").start();

        }

    }

}

Program execution results are as follows: Abnormal reported java.util.ConcurrentModificationException

 

2, produced by reason ConcurrentModificationException

A thread is writing, another thread came to seize resources, will result in inconsistent data, and then reported concurrent modification exception.

 

3, Set thread safe solution

(1) A first solution

Creating collections Use Collections synchronization tools

 

import java.util.Collections;

import java.util.HashSet;

import java.util.Set;

java.util.UUID import;

 

public class ContainerSafeSetDemoOne {

    public static void main(String[] args) {

        Set<String> set = Collections.synchronizedSet(new HashSet<>());

        for (int i = 0; i < 30; i++) {

            new Thread(() -> {

                set.add(UUID.randomUUID().toString());

                System.out.println(set.toString());

            }, String.valueOf(i)).start();

        }

    }

}

(2) The second solution

Alternatively CopyOnWriteArraySet concurrent programming class HashSet

 

import java.util.Set;

java.util.UUID import;

import java.util.concurrent.CopyOnWriteArraySet;

 

public class ContainerSafeSetDemoTwo {

    public static void main(String[] args) {

        Set<String> set = new CopyOnWriteArraySet<>();

        for (int i = 0; i < 30; i++) {

            new Thread(() -> {

                set.add(UUID.randomUUID().toString());

                System.out.println(set.toString());

            }, String.valueOf(i)).start();

        }

    }

}

CopyOnwriteArraySet container vessel that is copy-on-write. Element added to a container when the container is not directly to the current Object [] is added, but the first current container Object [] for Copy, a copy of a new container object [] newElements, and then to a new container Object [] the newElements Lane added element, after adding an element, then references to the new container setArray (newElements) the original container; the benefits of doing so is concurrent reading of CopyOnWrite container without the need to lock, because the current container does not add any element . Therefore, the container is also a separate read and write CopyOnWrite thought, reading and writing is different containers.

 

    public boolean add(E e) {

        return al.addIfAbsent(e);

}

 

    /**

     * Appends the element, if not present.

     *

     * @param e element to be added to this list, if absent

     * @return {@code true} if the element was added

     */

    public boolean addIfAbsent(E e) {

        Object[] snapshot = getArray();

        return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :

            addIfAbsent(e, snapshot);

}

 

    /**

     * A version of addIfAbsent using the strong hint that given

     * recent snapshot does not contain e.

     */

    private boolean addIfAbsent(E e, Object[] snapshot) {

        final ReentrantLock lock = this.lock;

        lock.lock();

        try {

            Object[] current = getArray();

            int len = current.length;

            if (snapshot != current) {

                // Optimize for lost race to another addXXX operation

                int common = Math.min(snapshot.length, len);

                for (int i = 0; i < common; i++)

                    if (current[i] != snapshot[i] && eq(e, current[i]))

                        return false;

                if (indexOf(e, current, common, len) >= 0)

                        return false;

            }

            Object[] newElements = Arrays.copyOf(current, len + 1);

            newElements [len] = a;

            setArray(newElements);

            return true;

        } finally {

            lock.unlock();

        }

    }

Guess you like

Origin blog.csdn.net/longgeqiaojie304/article/details/89819422