"In-depth understanding of JVM" Chapter 13 thread-safe lock and optimization

table of Contents

Chapter 13 thread-safe lock and optimization

13.2 thread-safe

What is thread safe?

When multiple threads access an object, if not consider alternate scheduling and execution under the environment of these threads at runtime and does not require additional synchronization, or perform any other operation in coordination caller, calling the object's behavior you can get the right result, that this object is thread safe.

 

Thread-safe code must have a feature: the code itself encapsulates all the necessary means to guarantee the correctness (such as mutual exclusion synchronization, etc.), so that callers do not care about multithreading issues, but need not own any measures taken to ensure proper multi-threaded transfer.

 

Thread Safety 13.2.1 Java language

Premise: the existence of shared data access between multiple threads

(Brian Goetz papers presented)

Thread-safe "level of security" to be sorted by the weak strong follow, divided into the following five categories:

Immutable, absolute security thread, the thread is relatively safe, thread-compatible, and thread-hostile

1. immutable

Immutable objects must be thread-safe. Later, because of immutable objects are created out to the outside, its visibility will never change.

1) shared data is a basic data types. Use the keyword final modification to ensure that the definition of immutable time.

2) shared data object, the object's behavior to ensure that does not produce any change in their job status.

Java.lang.String class objects are immutable, substring (), replace () method does not change like the original value, it will return a String object to a new configuration.

Ensuring that the object behavior does not affect the easiest way to own state, with the state of the object variables are declared final.

In Java immutable class, String, enumerated types, Long, Double, BigInteger, BigDecimal.

 

2. Absolute thread safety

"No matter how run-time environment, the caller does not need any additional synchronization measures."

Java API noted in a thread-safe class, most are not absolute thread safety.

private static Vector<Integer> vector = new Vector<Integer>();
​
public static void main(String[] args) {
   while (true) {
      for (int i = 0; i < 10; i++) {
         vector.add(i);
      }
      Thread removeThread = new Thread(new Runnable() {
         public void run() {
            for (int i = 0; i < vector.size(); i++) {
              vector.remove(i);
            }
         }
      };
      Thread printThread = new Thread(new Runnable() {
          public void run() {
             for (int i = 0; i < vector.size(); i++) {
                System.out.println(vector.get(i))
             }
          }
      };
      removeThread.start();
      printThread.start();
      while (Thread.activeCount() > 20);
   }
}

Vector's get (), remove (), size () are synchronized, but do not take appropriate measures if the synchronization code is still insecure.

 

3. Relative thread-safe

Thread-safe in the usual sense, it is necessary to ensure that this object is a separate thread safe operation without additional assurance measures, but for successive calls in a particular order, require the use of additional synchronization means when you call to ensure the correctness of the call.

Java, most of thread-safe classes are of this type, such as Vector, HashTable, Collections.synchronizedCollection () method wraps off the set.

      Thread removeThread = new Thread(new Runnable() {
         public void run() {
            synchronized(vector) {
               for (int i = 0; i < vector.size(); i++) {
                     vector.remove(i);
               }
            }
         }
      };
      Thread printThread = new Thread(new Runnable() {
          public void run() {
             synchronized(vector) {
                for (int i = 0; i < vector.size(); i++) {
                  System.out.println(vector.get(i))
                }
             }
          }
      };

 

4. thread-compatible

Refers to the object itself is not thread-safe, can be used to ensure synchronization means objects can be used in a safe environment in the event of concurrent calls.

We usually say that a class is not thread-safe, refers to this situation. Such as ArrayList and HashMap.

 

The thread-hostile

Refers to the end regardless of whether calls using synchronous measures to ensure that the object can not be used safely in a multithreaded environment.

Examples: suspend Thread class () method and resume () method. Two threads simultaneously by a thread object, a call to suspend (), a call to resume (), may lead to a deadlock. For this reason, these two methods are

JDK declared @Deprecated.

 

13.2.2 thread-safe implementation

How to implement a thread-safe?

Synchronization refers to a plurality of threads concurrently access shared data, shared data to ensure that only one thread (or some, using semaphore) to use.

1. mutex synchronization

Mutex is a means of synchronization, implementation has

1) synchronized keyword

After compilation, the formation of monitorenter and monitorexit instructions before and after the two-byte code sync block.

In the JVM specification, when executed monitorenter instruction, first attempts to obtain a lock object. If the object has not been locked, or only the current thread object lock, the lock count is incremented.

Monitorexit instruction executed when the lock counter is decremented by 1 when the counter becomes 0, the lock is released. If the acquisition target lock fails, the current thread is blocked waiting.

 

2) java.util.concurrent package reentrant lock ReentrantLock

Compared synchronized, ReentrantLock has some advanced features: interruptible wait, fair locks, lock can be bound to a number of conditions.

Interruptible wait: thread holding the lock for a long time not to release the lock, the thread waiting for the lock can give up waiting, do other things

Fair lock: synchronized lock non-fair, ReentrantLock default is unfair, but it can be a fair lock ReentrantLock

Binding can lock multiple conditions: Condition a plurality of objects can be bound ReentrantLock

 

2. Non-blocking synchronization

Mutex synchronization will be main problem is that performance problems thread blocks and thread wakes brought this synchronization to block synchronization.

Mutex synchronization for pessimistic locking strategy, the task is not correct synchronization measures, there will be problems, regardless of whether there is a competition to share data, to be locked.

With the development of hardware instruction set, you can use optimistic locking strategy, which is to perform an operation, if there is no thread contention, the operation will be successful; if there is a thread competition, keep retrying until it succeeds.

 

CASE

What is CAS command?

CAS spelling as Compare and Swap, compare and exchange.

CAS is cpu command (related hardware), which has three operands, namely memory address, the old value A, the new value of N.

When the CAS instruction is executed, only if and when the value of the old value of the memory address A is updated to the new value N. Whether or not the update is successful, it will return the old value.

CAS includes instruction conflict detection value updating +, requires multiple operations semantically, it is necessary to guarantee the atomicity of the hardware by a processor instruction.

 

Java in the CAS.

Several methods are sun.misc.Unsafe class bottom inside compareAndSwapInt, compareAndSwapLong the like,

In doing virtual machine processing, compiled by the CAS instruction is a platform-dependent.

 

CAS logic vulnerabilities: ABA problem

The old value is changed by the memory A B, then changed to A, but the CAS mistaken value memory has not been modified.

java.util.concurrent provides a AtomicStampedReference to solve this problem, the principle of variable carries the version number (A1 -> B2 -> A3).

This class is relatively tasteless, ABA problem does not affect the correctness of concurrency in most cases.

 

3. No synchronization scheme

The method does not involve the sharing of data, natural does not require any measures to ensure the accuracy of synchronization, such code is inherently thread-safe

1) reentrant code

Analyzing reentrant code principle: If a method, the same input data, always returns the same result.

 

2) Thread Local Storage

Code shared data is performed in the same thread, the shared data visible range is limited within the same thread

In Java ThreadLocal class implements Thread Local Storage.

Example: The classic web interaction model, a request corresponds to a thread server, the server can use thread local storage address security thread

 

13.3 Lock optimization

In order to more efficiently share data between threads, and to resolve competition issues, JVM optimization techniques to achieve a variety of locks.

Including spin locks, locks elimination, lock coarsening, lightweight lock, lock biased.

1. adaptive spin lock spin

Spinlocks

background:

1) exclusive synchronized greatest impact on performance is achieved blocked (suspend and resume the thread thread into kernel mode needs to complete).

2) At the same time, in many applications, when access to shared data, the thread that holds the lock will only last a short period of time. To this very short time to suspend and resume the thread is very worthwhile.

Principle: multicore processors, two or more threads can be executed in parallel, allowing the thread execution request of a busy lock loop (spin) Wait a minute, do not give up the processor execution time to see if the thread holding the lock We will soon release the lock.

Advantages: due to spin a thread waiting for the lock and the process does not cause a context switch, and therefore more efficient;

Cons: spin the thread has been waiting process execution of the CPU occupancy but does not handle any task, so if the process is too long, it will cause a waste of CPU resources.

 

Adaptive spin locks

Principle: Adaptive conventional spin-spin can be empirically waiting time, calculate a reasonable The spin latency.

If a lock on the same object spin-wait just successfully won the locks, and thread holding the lock is in operation, the virtual think this is likely to spin again successful, will allow the spin to wait longer, such as 100 cycles.

If for a lock, spin rarely succeed too, after acquiring the lock may be omitted when the spin off process, to avoid wasting resources.

 

2. Lock elimination

Lock means the immediate elimination compile at run time, although some of the code is detected synchronization requirements, but there can be no competition to share data, which will eliminate the lock code.

Lock eliminate the main judge based on escape analysis, if it is judged in a piece of code, the data will not escape out of the heap by other threads access to, think they are thread-private, without the need for synchronization lock.

 

3. 锁粗 of

Lock coarsening refers to the virtual machine detects a series of operations are repeated for the same object lock, unlock (even if no thread contention, frequently mutually exclusive synchronization causes unnecessary performance loss), the lock will extend to the entire range of synchronous operation external sequence.

 

4. Lock escalation

JDK1.6 later version exists in dealing with the concept of synchronization lock lock escalation, JVM for processing synchronization lock is biased locking from the start, with the increasingly competitive approach to lightweight upgrade from biased locking lock, the final upgrade to the heavyweight lock.

The lock information in advance of the existence of Java objects.

 

Java object form following two heads (JVM to Example 32)

Non-array type objects.

Wherein, Mark Word or stored object hashcode lock information, Klass Word stores a pointer to an object of type data.

The object is an array type.

For array types, array length of the length of the memory array.

 

During operation, the data stored in Mark word will change the lock flag is changed.

1) biased locking

"Bias is a lock for locking means to optimize the operation of its core idea is: If a thread to get the lock, then the lock to enter bias mode when the thread again request a lock, so no need to do any synchronization operations. it saves a lot about the operation of the lock application, thereby improving application performance. Therefore, for the little lock contention occasions, tend to have better locks optimization results, because many times in a row is very likely that the same request with a thread lock and more fierce competition for locking the occasion, the effect is poor, because in a competitive situation, the most likely scenario is that every time a different thread to request the same lock. such models tend to fail, so might as well biased locking is not enabled. "

 

When one thread to access sync block is recorded in the thread id in the object header Mark Word.

Later when entering and exiting the synchronized block again, without the use of CAS for locking and unlocking, only the test object head Mark word in whether it is biased locking and thread id is your own id.

1) If the test is successful (as biased locking and thread id of their own), indicating that the thread has received lock.

2) If the test fails

If Markd word in biased locking flag is set to 1 (ie, the current is biased locking), CAS will try to use the thread id Mark word is set to own.

If the current is not biased locking using CAS lock contention.

 

2) Lightweight lock

Lightweight lock lock:

Before performing sync block, since the JVM creates a space for storing the locks, and Mark word object header record copied to lock in the current thread stack frame.

Then, try to replace an object header Mark word pointer to point to the locks used CAS.

If successful, the current thread to acquire the lock; if it fails, other threads in the competition represents the lock, the current thread tries to use spin to get the lock.

 

Lightweight lock unlock:

When unlocked, the lock will attempt to replace the record information back Mark word to use CAS.

If successful, it means that there is no competition occurs; if it fails, indicating the current presence of lock contention, lock expands heavyweight lock (lock is the traditional heavyweight lock mutex).

 

In favor of locks, lock lightweight, heavyweight lock

Biased locking

Role: to eliminate biased locking synchronization primitives in a non-competitive situation, to further improve program performance.

Advantages: biased locking synchronization can be improved but there is no competitive process performance. But if the lock object is often multiple threads compete, that tend to lock superfluous.

Applicable scene: suitable for only one thread synchronization block access to scenes.

In favor of the lightweight lock lock

Difference 1) and the lock Lightweight: Lightweight locks are used in case of contention-free operation of CAS instead of using the mutex, thereby achieving synchronization; biased lock is completely abolished in the absence of competition synchronous case.

2) the same point Lightweight locks: they are optimistic locking, you do not think that any other thread lock contention during synchronization.

 

Lightweight lock

Background: "Lightweight Lock" is relative to the "heavyweight Lock", and is the traditional heavyweight lock lock.

Essence: Use CAS to replace mutually exclusive synchronization.

Pros: The thread does not block competition, improve the response speed of the program.

Cons: competing threads still unable to get a lock, using spin will consume CPU

Lightweight and heavyweight lock locks comparison:

1) heavyweight pessimistic lock is a lock, it is always considered a number of threads to lock contention, so it every time processing of shared data, regardless of whether the current system is really a thread lock in the competition, it will use exclusive synchronization to ensure the security thread;

2) The lock is a lightweight optimistic locking, which locks think the probability of the existence of competition is relatively small, so it does not use a mutex synchronization, but the use of CAS operation to acquire the lock, which could reduce the "exclusive use of synchronization mutex "bring performance overhead.


Heavyweight lock

Advantages: competition does not use spin thread, do not consume CPU

Disadvantages: thread is blocked, slow response time

 

Guess you like

Origin www.cnblogs.com/yeyang/p/12580649.html
Recommended