[About 7 synchronization methods of threads]

1. The principle of lock

Every object in Java has a built-in lock

When the program runs to a non-static synchronized synchronized method, the lock associated with the current instance (this instance) of the executing code class is automatically acquired. Acquiring a lock on an object is also known as acquiring a lock, locking an object, locking on an object, or synchronizing on an object.

The object lock only works when the program runs to a synchronized synchronization method or code block.

 

An object has only one lock. So, if one thread acquires the lock, no other thread can acquire the lock until the first thread releases (or returns) the lock. It also means that no other thread can enter a synchronized method or block of code on the object until the lock is released.

 

Releasing a lock means that the thread holding the lock has exited a synchronized method or block of code.

 

There are a few key points about locking and synchronization:

1), only methods can be synchronized, not variables and classes;

2), there is only one lock per object; when synchronization is mentioned, it should be clear on what synchronization? That is, on which object is it synchronized?

3) It is not necessary to synchronize all the methods in the class, the class can have both synchronized and non-synchronized methods.

4) If two threads want to execute a synchronized method in a class, and the two threads use the same instance to call the method, then only one thread can execute the method at a time, and the other needs to wait until the lock is released. That is: if a thread acquires a lock on an object, no other thread can enter any synchronized method in the class (of the object).

5) If the thread has synchronized and unsynchronized methods, the unsynchronized method can be freely accessed by multiple threads without being restricted by locks.

6) When the thread sleeps, any locks it holds will not be released.

7), the thread can obtain multiple re-entry (synchronized) locks. For example, calling the synchronization method of another object in the synchronization method of one object will acquire the synchronization lock of the two objects.

8) Synchronization damages concurrency, and the scope of synchronization should be reduced as much as possible. Synchronization can not only synchronize the entire method, but also a part of the code block in the method.

9) When using a synchronized code block, you should specify which object to synchronize on, that is, which object's lock to acquire.

 

 

Why use sync? 

Java allows multi-threaded concurrency control. When multiple threads operate a shared resource variable at the same time (such as data addition, deletion, modification and query), it will lead to inaccurate data and conflict with each other. Therefore, a synchronization lock is added to avoid this Before the thread completes the operation, it is called by other threads, thus ensuring the uniqueness and accuracy of the variable.

 

 

 

1. Synchronization method 

    That is, there is a method modified by the synchronized keyword. Since each object of java has a built-in lock, when a method is decorated with this keyword, the built-in lock will protect the entire method. Before calling this method, you need to acquire the built-in lock, otherwise it will be blocked.   

Note: The synchronized keyword can also modify static methods. If the static method is called at this time, the entire class will be locked.

 

2. Synchronized code blocks 

    That is, a statement block modified by the synchronized keyword. The statement block modified by this keyword will be automatically added with built-in lock to achieve synchronization.

Note: Synchronization is an expensive operation, so it should be minimized. Usually it is not necessary to synchronize the entire method, just use the synchronized block to synchronize critical code. 

 

3. Use special domain variables (volatile) to achieve thread synchronization

    The a.volatile keyword provides a lock-free mechanism for accessing domain variables, 

    b. Using volatile to modify the field is equivalent to telling the virtual machine that the field may be updated by other threads, 

    c. So every time the field is used, it needs to be recalculated instead of using the value in the register 

    d.volatile does not provide any atomic operations, nor can it be used to modify variables of final type 

 

 

4. Use reentrant locks to achieve thread synchronization

    A java.util.concurrent package was added to support synchronization in Java SE 5.0. The ReentrantLock class is a reentrant, mutually exclusive lock that implements the Lock interface. It has the same basic behavior and semantics as using the synchronized method and fast, and extends its capabilities.

 

    Common methods of the ReenreantLock class are:

        ReentrantLock() : Create a ReentrantLock instance 

        lock() : acquire the lock 

        unlock() : release the lock 

Note: ReentrantLock() also has a construction method that can create a fair lock, but it is not recommended because it can greatly reduce the efficiency of the program 

 

Note: Regarding the choice of Lock object and synchronized keyword: 

   a. It is best to use neither of the two, and use a mechanism provided by the java.util.concurrent package to help users deal with all lock-related code. 

   b. If the synchronized keyword can meet the user's needs, use synchronized because it simplifies the code 

   c. If you need more advanced functions, use the ReentrantLock class. At this time, you should pay attention to releasing the lock in time, otherwise there will be a deadlock. Usually, the lock is released in the finally code. 

 

 

5. Use local variables to achieve thread synchronization 

    If ThreadLocal is used to manage variables, each thread that uses the variable gets a copy of the variable, and the copies are independent of each other, so that each thread can modify its own copy of the variable at will without affecting other threads.

  

Common methods of the ThreadLocal class

    ThreadLocal() : Create a thread local variable 

    get() : returns the value in the current thread copy of this thread local variable 

    initialValue() : Returns the current thread's "initial value" of this thread-local variable 

    set(T value) : Sets the value in the current thread copy of this thread-local variable to value

 

Note: ThreadLocal and synchronization mechanism 

  a.ThreadLocal and synchronization mechanisms are both to solve the access conflict problem of the same variable in multiple threads. 

  b. The former adopts the method of "space for time", and the latter adopts the method of "time for space"

 

 

6. Use blocking queue to achieve thread synchronization

    The first five synchronization methods are all thread synchronization implemented at the bottom layer, but in actual development, we should try to stay away from the bottom layer structure. Using the new java.util.concurrent package in javaSE5.0 will help simplify development. This section mainly uses LinkedBlockingQueue<E> to achieve thread synchronization LinkedBlockingQueue<E> is a blocking queue based on connected nodes with any range. The queue is in a first-in, first-out order (FIFO). The queue will be explained in detail later~ 

   

   Common methods of the LinkedBlockingQueue class 

    LinkedBlockingQueue() : Create a LinkedBlockingQueue with a capacity of Integer.MAX_VALUE 

    put(E e) : add an element to the end of the queue, block if the queue is full 

    size() : returns the number of elements in the queue 

    take() : remove and return the head of the queue, block if the queue is empty 

 

 

Note: BlockingQueue<E> defines the common methods of blocking queues, especially the three methods of adding elements, we should pay more attention, when the queue is full:

  add() method throws an exception

  offer() method returns false

  put() method will block

 

 

 

7. Thread synchronization using atomic variables

The fundamental reason for needing to use thread synchronization is that operations on ordinary variables are not atomic. So what is an atomic operation?

Atomic operation refers to the operation of reading the variable value, modifying the variable value, and saving the variable value as a whole - these actions are either completed at the same time or not.

A utility class for creating atomic type variables is provided in the util.concurrent.atomic package of java, which can simplify thread synchronization.

 

Among them, the AtomicInteger table can atomically update the value of int, which can be used in applications (such as counters that increase atomically), but cannot be used to replace Integer; extensible Number allows those tools and utilities that deal with opportunistic numbers to perform Unified access.

 

Common methods of AtomicInteger class:

AtomicInteger(int initialValue) : Creates a new AtomicInteger with the given initial value

addAddGet(int dalta) : Atomically adds the given value to the current value

get() : get the current value

 

Supplement - atomic operations mainly include:

  read and write operations on reference variables and most primitive variables (except long and double);

  For all read and write operations on volatile-modified variables (including long and double).

Guess you like

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