Thread safety and thread unsafety understanding

       Thread safety means that when multi-threaded access is used, a locking mechanism is adopted. When a thread accesses a certain data of this class, it is protected, and other threads cannot access it until the thread finishes reading, and other threads can use it. There will be no data inconsistency or data pollution. Thread insecurity means that data access protection is not provided. It is possible that multiple threads change data successively, resulting in dirty data.

 

concept:

        If your code is in a process with multiple threads running at the same time, these threads may be running this code at the same time. If the result of each run is the same as the result of a single-threaded run, and the values ​​of other variables are the same as expected, it is thread-safe.

        In other words: the interface provided by a class or program is an atomic operation for threads or switching between multiple threads will not lead to ambiguity in the execution result of the interface, that is to say, we do not need to consider the problem of synchronization.

        Thread safety problems are caused by global variables and static variables.

        If each thread has only read operations on global variables and static variables, but no write operations, generally speaking, this global variable is thread-safe; if multiple threads perform write operations at the same time, thread synchronization generally needs to be considered, otherwise It may affect thread safety.


safety:

        For example, an ArrayList class, when adding an element, it may have two steps to complete: 1. Store this element in the position of Items[Size]; 2. Increase the value of Size.

In the case of single-threaded operation, if Size = 0, after adding an element, this element is at position 0, and Size = 1;

        In the case of multi-threading, such as two threads, thread A stores the element at position 0 first. But at this time, the CPU schedules thread A to suspend, and thread B gets a chance to run. Thread B also adds elements to this ArrayList, because Size is still equal to 0 at this time (note that we are assuming that adding an element takes two steps, and thread A only completes step 1), so thread B also adds the element Stored in position 0. Then both thread A and thread B continue to run, increasing the value of Size.

        Well, let's take a look at the situation of ArrayList. There is actually only one element, which is stored in position 0, and Size is equal to 2. This is "thread unsafe".


safety:

        Thread safety is not a true or false proposition. The methods of Vector are all synchronized, and Vector is explicitly designed to work in a multithreaded environment. But its thread safety is limited, i.e. there are state dependencies between some methods (similarly, if the Vector is modified by other threads during the iteration, the iterator returned by Vector.iterator() will throw ConcurrentModifiicationException ).

        There is no widely accepted classification system for the thread-safety levels commonly found in Java classes, but it is important to document as much of the thread-safe behavior as possible when writing classes.

        Bloch gives a taxonomy to describe five categories of thread safety: immutable, thread-safe, conditional thread-safe, thread-compatible, and thread-opaque. It doesn't matter if you use such a system or not, as long as the thread-safety features are explicitly documented. This system has its limitations -- the lines between categories aren't 100 percent clear, and there are cases where it doesn't take care of it -- but this system is a good place to start. At the heart of this classification system is whether the caller can or must surround an operation (or sequence of operations) with external synchronization. The following sections describe each of these five categories of thread safety.


immutable

        Immutable objects are guaranteed to be thread-safe and never require additional synchronization. Because an immutable object, as long as it is constructed correctly, its externally visible state will never change, and it will never be seen in an inconsistent state. Most of the basic numeric classes in the Java class library such as Integer, String and BigInteger are immutable.

        It should be noted that for Integer, this class does not provide an add method, and the addition is performed directly using +. The + operation is not thread safe. This is the source of the class AtomicInteger that provides atomic operations.


thread safety

        Thread-safe objects have the properties described above in the "Thread-safety" section -- the constraints imposed by the class's specification remain in effect when the object is accessed by multiple threads, regardless of the runtime environment. extra sync. This thread-safety guarantee is very strict -- many classes, such as Hashtable or Vector, fail to satisfy this strict definition.


Conditional

        Conditionally thread-safe classes can be thread-safe for individual operations, but certain sequences of operations may require external synchronization. The most common example of conditional thread safety is traversing the iterators returned by Hashtable or Vector or -- the fail-fast iterators returned by these classes assume that the underlying collection will not change while the iterator is traversing. To ensure that other threads do not mutate the collection while traversing, the iterating thread should ensure that it has exclusive access to the collection for traversal integrity. Typically, exclusive access is guaranteed by synchronization on the lock -- and the class's documentation should state which lock (usually the object's intrinsic monitor) is.

        If you document a conditionally thread-safe class, then you should document not only that it is conditionally thread-safe, but also which sequences of operations must be prevented from concurrent access. Users can reasonably assume that other sequences of operations do not require any additional synchronization.


thread compatible

        Thread-compatible classes are not thread-safe, but can be used safely in concurrent environments with proper use of synchronization. This might mean wrapping each method call with a synchronized block, or creating a wrapper object where each method is synchronized (like Collections.synchronizedList() does). It may also mean surrounding certain sequences of operations with synchronized blocks. To get the most out of thread-compatible classes, if all calls use the same block, then the caller should not be required to synchronize on that block. Doing so will cause the thread-compatible object to be contained as a variable instance in other thread-safe objects, allowing it to take advantage of the synchronization of its owner object.

        Many common classes are thread compatible, such as the collection classes ArrayList and HashMap, java.text.SimpleDateFormat, or the JDBC classes Connection and ResultSet.


thread opposition

        Thread-opposed classes are those that cannot be safely rendered in concurrent use, regardless of whether external synchronization is invoked. Thread antagonism is rare and usually occurs when a class modifies static data that affects the behavior of other classes executing in other threads. An example of a thread-opposite class is a class that calls System.setOut().

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326824711&siteId=291194637