In-depth understanding of the Java Virtual Machine - Chapter XIII - Efficient Concurrency

Thread Safety

When multiple threads access an object, if you do not consider these thread scheduling in the operating environment and alternately perform and does not require additional synchronization, or additional coordinated operations in local call, call the object's behavior can get the correct result, the object is thread safe.

Java thread-safe

Various operations of data classification shared class 5:

  1. Immutable: immutable objects must be thread-safe. The basic data type is defined as a final immutable. String, Number, Long and other values ​​are immutable, but AtomicInteger Number of atoms is immutable class.
  2. Absolute thread safety: no matter how run-time environment, do not need any additional synchronization measures. Though such as Vector class is thread-safe, because its methods are combined with a synchronized, but if you call it on the outside with two threads, an access element of a deleted element, so if the outside is not synchronous, then it will make access to just delete elements and error. So Vector is not an absolute thread safety.
  3. Relative thread safety: ensuring that the object individual operations are thread-safe. Such as Vector is relatively thread-safe.
  4. Thread-compatible: the object itself is not thread-safe, but when called by means of synchronization can guarantee thread safety. Such as ArrayList and HashMap.
  5. Thread-hostile: whether or not to take synchronous measures, they can not use concurrent code in a multithreaded environment. As of Thread suspend () and resume () method, while operating a thread interrupted and resumed once concurrency, synchronization is whether or not there is the risk of deadlock. That is a thread suspend suspend itself (does not suspend the release of the lock held by the lock unless resume), if the thread due to resume where you want to get suspend thread lock blocked before the resume, then a deadlock occurred. Reference https://www.jianshu.com/p/7a123f212ca1 .

Thread-safe implementation

Mutex synchronization

Mutex is a means of achieving synchronization. Need to block and wake-up that performance degradation, also known as blocking synchronization, pessimistic locking. Regardless of whether the shared data will need to lock contention occurs.

The most basic means of mutual exclusion is synchronized. Will form around the block synchronization and monitorenter monitorexit, attempt to acquire the lock when performing monitorenter, if not already hold their own or hold the lock counter is incremented, execution monitorexit will be minus 1, until it releases the lock 0 . If you fail to obtain the lock will be blocked state.

In addition there synchronnized JUC reentrant lock (of ReentrantLock), are provided with line reentrancy, but the codes are different wording, a level API for the mutex (lock and unlock methods fitting try / finally statement is implemented), a native syntax level mutex. RenetrantLock more than 3 advanced features:

  • Interruptible wait: When long thread holding the lock does not release the lock, the thread waiting for the lock can give up waiting instead to deal with other things
  • Fair locks: multiple threads wait for a lock, chronologically application to obtain a lock. Each lock is fair rather than waiting thread has access to the lock, synchronized non-fair locks
  • Lock binding conditions: a Reentrant can bind multiple Condition objects, but to be synchronized and associated with more than one condition when you have to add an extra lock, Reentrant only multiple calls newCondition.

Non-blocking synchronization

Optimistic locking. Concurrency strategy to carry out its operations, if there are no threads in shared data, and that the operation is successful; if there is contention, then the conflict, to take other measures to compensate (common compensation is keep retrying until it succeeds). So do not send thread is suspended.

Optimistic locking operation and the need to ensure that conflict detection is atomic, if you use synchronization to ensure mutual exclusion would be meaningless, and therefore need the hardware to get this done. The CAS command.

CAS three operands: memory address A, the expected value of the old O, the new value N. A if and only if V is updated in line with the expected value O if the old to the new value N, and return the old value O, provided no update do not meet. This operation is an atomic operation.

No synchronization scheme

Guarantee thread safety does not necessarily need to be synchronized, no causal relationship between the two. If a method does not involve sharing data, then without any synchronization. For example, the following two types of codes are inherently thread-safe:

  • Reentrant code is: also known as pure code, can be interrupted at any time code execution, turn to perform another piece of code (including calls itself recursively), the original program without error after control is returned. Reentrant code is thread-safe, in turn, it is not. There is a simple method of determination: If the method returns the result is predictable, as long as the same input data can return the same results, then it satisfies the requirements reentrant. For example, and does not depend on the heap data common system resources, non-reentrant code without calling state quantities used are parameter.
  • Thread Local Storage: If the required code data must be shared with other code, then see if you can ensure that code for these shared data is performed in the same thread. Such as consumer queues are guaranteed a thread consumption in the process is complete, in particular in a web server corresponding to a thread request.

Lock optimization

Lock optimization techniques: Adaptive spin locks elimination, lock coarsening, lightweight lock, lock biased,

And spin-spin locks adaptive

Mutex synchronization performance overhead is the biggest suspend and resume the thread, into the kernel mode needs to complete. Most of the state locking shared data only lasts for a short time, so take this time to suspend and resume not worth it, so you can get behind the lock request "Waiting for what," but do not give up the processor execution time , just perform free circulation (spin), which is called the spin lock.

Spin can not replace blocked. If the time exceeds the cost of the spin thread suspend and resume time overhead, then the processor resources consumed in vain. The default spin 10 times, can -XX: PreBlockSpin change. JDK1.6 after the introduction of spin lock spin time is not fixed, but by the same time in a locked lock spin time and the owner of the state to decide. If successful the last spin and thread is running, the spin will be considered to be successful, so the spin will last longer, if a spin lock is rarely successful future for possible direct spin omit direct hang.

Lock elimination

Lock means even eliminating compile time, a number of requirements for code synchronization, it is detected to the common data lock contention does not exist to eliminate. StringBuffer append example of synchronous blocks, which reference will not escape into the concatString, other threads can not access to him, so the lock can be safely eliminated.

public String concatString(String s1, String s2, String s3) {
        StringBuffer sb = new StringBuffer();
        sb.append(s1);
        sb.append(s2);
        sb.append(s3);
        return sb.toString();
}

Lock coarsening

In principle, the synchronization is recommended that the scope is smaller, only synchronization occurs only in the actual scope of shared data. If you repeatedly lock unlock the same object in a series of operations, or even appear locked in for loop, even if not competition, frequent mutual exclusion synchronization can lead to performance loss. E.g. above append, the virtual machine will lock into a first range of extension append to the last append.

Lightweight lock

Is relatively lightweight operating system lock mutex lock be accomplished using conventional terms, the traditional heavyweight lock is locked.

If you start a thread to acquire the lock object header flag is not locked, with the CAS operation object header flag is a lightweight lock, hold a lock on the object. If the update fails, it is determined that the object mark word points to the current thread's stack frame is the show already has the lock, direct access to the synchronized block, otherwise indicating that the lock is accounted for by other threads. If more than two threads contend with a lock, then the lock becomes lightweight heavyweight lock.

Based on a lightweight lock is to enhance the synchronization performance of "Most lock in the whole cycle is synchronized competition does not exist", which is an empirical data. There is no competition, then use the CAS operation avoids the use of mutually exclusive overhead.

Biased locking

Lock will be biased in favor of the first thread gets it, if in the next execution, the lock has not been acquired by other threads, biased locking thread that holds do not need to be synchronized. If you have been holding biased lock, the lock according to whether the object is locked or unlocked converted to lightweight lock state.

 

Guess you like

Origin www.cnblogs.com/yjou/p/11270307.html