Java Concurrency entry (XVIII) More on thread safety

First, you do not need thread-safe lock scene

Are several scenarios do not need thread-safe lock can do:

1. immutable objects

2. Thread closed

3. Stack closed

4.ThreadLocal

I, immutable objects

Concurrent Programming classic description of the object invariance meet the following conditions:

1. The status will not change after the object is created.

2. All fields are final object type.

3. During creating an object, this reference does not overflow.

For the actual description is not entirely accurate Point 2:

1. As long as member variables are private, and only provides read-only operation, it is possible to achieve thread-safe, it does not necessarily require final modification, note here that it is possible, the reasons given in the first 2:00.

2. If the member variable is an object, and an external writable, then there is no guarantee thread safety, such as:

public class Apple {
    public static void main(String[] args) {
        Dictionary dictionary = new Dictionary();
        Map<String, String> map = dictionary.getMap();
        //这个操作后,导致下一步的操作结果和预期不符,预期不符就不是线程安全
        map.clear();
        System.out.println(dictionary.translate("苹果"));
    }
}

class Dictionary {

    private final Map<String, String> map = new HashMap<String, String>();

    public Dictionary() {
        map.put("苹果", "Apple");
        map.put("橘子", "Orange");
    }

    public String translate(String cn) {
        if (map.containsKey(cn)) {
            return map.get(cn);
        }
        return "UNKONWN";
    }

    public Map<String, String> getMap() {
        return map;
    }
}
复制代码

Therefore, the correct understanding of the same object should be:

1. After the object is created the state does not change (all member variables do not change)

2. Only read-only operations.

3. The members of the object at any time will not overflow (members not to write to other external objects), not just in the construction time.

Other books and training should be mentioned in the same category with the final modification to prevent class is unsafe, following Cheng Houzai class, personally feel that the parent class and subclass of itself is not an object, we say that a class is thread safe to say that this class itself, without the need to be concerned about whether it is safe subclass, only caveat is: member variables of the parent class is protected modification, the subclass inherits modify it, then the parent class and subclass has been a thread calls the same, leading to the father class insecurity.

II, thread closed

If the object is only used in a single thread, not multiple threads share, which is the thread closed.

Applications such as web access database connection pool database connections, each thread is an independent web request, when a request is acquired after a database connection request to the other will not be used until the database connection is closed (the connection pool Back in) will be used by other requests.

III, the stack closure

Only the object in the local code block, the stack is closed, for example:

     public void print(Vector v) {
         int size = v.size();
         for (int i = 0; i < size; i++) {
             System.out.println(v.get(i));
         }
     }
复制代码

Variable size is a local variable (closed stacks), Vector is thread-safe container, so for this method is thread safe.

VI、ThreadLocal

By ThreadLocal object stored only on the current thread is visible, and therefore thread-safe.

Second, common misconceptions thread-safe scene

I, always thread-safe container security

Some security means a container thread thread-safe atomic operation, not all operations are safe, non-thread-safe operations such as: IF-AND-SET, iterative containers, for example:

public class VectorDemo {

    public static void main(String[] args) {
        Vector<String> tasks = new Vector<String>();
        for (int i = 0; i < 10; i++) {
            tasks.add("task" + i);
        }

        Thread worker1 = new Thread(new Worker(tasks));
        Thread worker2 = new Thread(new Worker(tasks));
        Thread worker3 = new Thread(new Worker(tasks));

        worker1.start();
        worker2.start();
        worker3.start();
    }
}

class Worker implements Runnable {

    private Vector<String> tasks;

    public Worker(Vector<String> tasks) {
        this.tasks = tasks;
    }

    public void run() {
        //如下操作非线程安全,多个线程同时执行,在判断时可能都满足条件,但实际处理时可能已经不再满足条件
        while (tasks.size() > 0) {
            //模拟业务处理
            sleep(100);
            //实际执行时,这里可能已经不满足tasks.size() > 0
            System.out.println(Thread.currentThread().getName() + " " + tasks.remove(0));
        }
    }

    private void sleep(long millis) {
        try {
            TimeUnit.MILLISECONDS.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
复制代码

Output log:

Thread-0 task0
Thread-1 task2
Thread-2 task1
Thread-1 task3
Thread-2 task5
Thread-0 task4
Thread-0 task6
Thread-1 task8
Thread-2 task7
Thread-1 task9
Exception in thread "Thread-0" Exception in thread "Thread-2" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 0
	at java.util.Vector.remove(Vector.java:831)
	at com.javashizhan.concurrent.demo.safe.Worker.run(VectorDemo.java:46)
	at java.lang.Thread.run(Thread.java:745)
java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 0
	at java.util.Vector.remove(Vector.java:831)
	at com.javashizhan.concurrent.demo.safe.Worker.run(VectorDemo.java:46)
	at java.lang.Thread.run(Thread.java:745)
复制代码

Which can be seen when a worker thread tasks.remove (0), due to the collection of data has not throw an exception. To achieve thread-safe lock will have non-atomic operation, the code is modified as follows:

    public void run() {
        //对非原子操作加锁
        synchronized (tasks) {
            while (tasks.size() > 0) {
                sleep(100);
                System.out.println(Thread.currentThread().getName() + " " + tasks.remove(0));
            }
        }
    }
复制代码

II, final modification of the object thread-safe

In the example described above, i.e. using Vector final modification nor thread-safe, it does not mean that the final modified objects are immutable object belongs thread safe.

III, volatile modification of the object thread-safe

The volatile keyword modified object can only guarantee visibility, these variables are not cached in the CPU cache, this will ensure you can see the latest value if thread A to modify the value of the volatile variable, then thread B after reading , but visibility does not equal thread-safe.

Third, broad and narrow thread-safe thread-safe

We say that Vector is thread-safe, but the above examples have been described: Not Vector operations are thread-safe under all scenarios, but obviously Vector has been recognized as thread-safe, how to explain this?

Thus, we can define the narrow and broad thread-safe thread-safe:

1. narrow sense: Every single operation objects are thread-safe

2. generalized: every single operation and the combined operation objects are thread-safe

For the example above Vector To modify generalized thread-safe, you need to do the second judge in the remove operation, if the container has no object, it returns null, the method signature can be modified to existsAndRemove, of course, in order to achieve broad thread-safe the modified method is also not just this one.

IV Summary

This paper describes an unlocked case scenario thread-safe, thread-safe and easy to misunderstand the scene, and then thread the narrow and broad security thread safety, understanding this, we can make clear when the lock, and when do not need locked, and thus more effective writing thread-safe code.

end.


Related Reading:
Java Concurrency (a) knowledge map
Java Concurrency (II) atom of
concurrent programming in Java (c) the visibility of
Java Concurrency (d) ordering of
concurrent programming in Java (e) creates a thread way Overview
Getting Started with Java concurrent programming (f) synchronized usage of
Java concurrent programming entry (seven) easy to understand and use wait and notify scene
Getting Started with Java concurrent programming (eight) thread lifecycle
Java concurrency entry (nine) deadlocks and deadlock locate
Java concurrency entry (X) lock optimized
Java concurrency entry (XI) limiting the flow restrictor Spring scene and realize
Getting Started with Java concurrent programming (xii) the producer and consumer model - code templates
Java concurrency entry (13) read-write locks and cache template
Java concurrency entry (xiv) application scenarios CountDownLatch
(fifteen) CyclicBarrier scenarios Java concurrency Introduction to programming
Getting Started with Java concurrent programming (XVI) thread pool seconds to understand the difference
Getting Started with Java concurrent programming (17) to master a drawing class and the common thread interface


Java Geek site: javageektour.com/

Guess you like

Origin juejin.im/post/5da338766fb9a04e0a37f4d1