Java Virtual machines-thread safety and lock optimization thread safety
Thread Safety: When multithreading accesses an object, the object is thread-safe if it is not necessary to consider the scheduling and alternation of these threads in the run-time environment, no additional synchronization is required, or if the caller performs any other coordinated operation, invoking the object's behavior can obtain the correct result.
In Java, thread safety is reflected in the fact that multiple threads access the same shared data, and if there is no data sharing with other threads at all in a piece of code, there is no thread safety issue.
The security level of thread safety, from strong to weak, can be divided into the following 5 classes.
Not variable
Immutable objects must be thread-safe, and the final keyword can achieve visibility. In Java, if you share data with the base data type, plus the final keyword to ensure that it is immutable, if it is an object, just ensure that it is an immutable object, such as a string object, any operation on it will not change the original value, but instead returns a new string object.
Absolute thread Safety
Meet the first thread-safety definition, that is, when multithreaded access to an object, if you do not have to consider these threads in the runtime environment scheduling and alternating execution, there is no need for additional synchronization, or any other coordinated operation of the caller, call this object's behavior can obtain the correct results, Then this object is thread-safe.
Relative Thread safety
In general, thread safety requires that the individual operations of this object be thread-safe and that no additional safeguards are required at the time of invocation, but additional synchronization may be used for successive calls in a particular order. Most thread-safe classes in the Java API are of this type, such as vectors, Hashtable, and so on.
Thread compatible
The object itself is not thread-safe, but can be used synchronously to ensure safe use in a concurrent environment. Generally speaking, the thread is unsafe refers to this type, Java most of the classes are, such as ArrayList, HashMap and so on.
Thread antagonism
It is not possible to use concurrency safely in a multithreaded environment, regardless of whether or not synchronization has been taken. is rare in Java.
Thread-Safe Implementation method Mutex synchronization
synchronization refers to concurrent access to shared data in multiple threads, and the data that is shared is guaranteed to be used by only one thread at a time. . Synchronization can be achieved in Java using a synchronized or a concurrent in a package. The latter has some more advanced features than the former:
- wait can be interrupted . When the thread holding the lock does not release the lock for a long time, the waiting thread can not abandon the wait and thus can handle other tasks.
- Fair lock . Multiple threads wait for the same lock, followed by first served in the order in which they were locked. Instead of any thread there is a chance to get a lock at this time. The lock in synchronized is unfair, the re-entry lock Reentrantlock is not fair by default, but you can specify that the parameter is set to a fair lock.
- locks bind multiple conditions . A reentrantlock can be bound to multiple condition objects.
In performance, the two are similar.
Non-blocking synchronization
Synchronization thread blocking is a pessimistic strategy, that is, whether or not to really share the data competition, should be locked. The CAS operation is an optimistic strategy, the first operation, if there is no shared data competition, the operation succeeds, otherwise conflict, then continue to retry until successful.
The CAS operation has 3 operands, namely the memory location V (which can be easily understood as the memory address of the variable in Java), the old expected value A, and the new value B, if and only if v conforms to the old expected value A, there will be a mind B update v value, otherwise not updated, indicating that the variable has been modified by another thread .
CAS has a problem: if the variable v is read to a value, Midway is modified to B, and finally modified back to the A,cas operation will be mistaken that the variable v has not been changed, which is called the "ABA Problem" CAS operation.
No synchronization
If you do not involve shared data, you do not need to synchronize. reentrant Code : can be interrupted at any point in the execution of the code, in turn to execute other code, after the return of control, the original program will not have any errors. the Reentrant code is thread-safe .
Lock optimized spin lock
If the lock state of the shared data is only a short period of time, it is not worthwhile to suspend and resume the thread for this time (all need to go to the kernel state), so let the thread behind the request lock wait for the following, but do not discard the processor's execution time. The wait here actually executes a busy loop, which is called spin.
Spin waits have a certain limit, the default value is 10 times, if more than this number, you will use the traditional way to suspend the thread. Adaptive spin locks are introduced in the JDK1.6. If, on the same object, the spin wait has just been successfully acquired, and the lock is in operation, the virtual machine considers the spin to be successful, and it is allowed to have a longer spin wait; conversely, if the spin is rarely successful for a lock, then it is possible to omit the spin process after acquiring the lock.
Lock removal
When virtual machines are compiled on the fly, they are required to synchronize on some code, but locks that cannot compete for shared data are detected. Lock elimination is based on "escape analysis" technology. All the data on the heap will not escape and be accessed by other threads, they can be treated as data on the stack, they are thread-private, and synchronous locking is not necessary.
Lock coarsening
If you repeatedly yoke or unlock an object, even the lock operation appears in the loop. The virtual machine detects this situation, and the lock is bolded to the outside of the operation. As an example,
publicstaticint0;for (int0100; i++) { synchronized (this) { j++; }}// 锁粗化synchronized (this) { for (int0100; i++) { j++; }}
Lightweight lock
Traditional locking mechanisms are called "heavyweight" locks, and lightweight locks are used to reduce the performance cost of traditional heavyweight locks using operating system mutexes without multi-threading competition.
The lock and unlock of the lightweight lock is done through the CAS operation, and if more than two threads are contending for the same lock, the lightweight lock expands into a heavyweight lock .
Lightweight locks can improve synchronization performance mainly because: for most locks, there is no competition throughout the synchronization cycle.
Biased lock
Lightweight noise-free, non-competitive use of CAS operations to eliminate the mutex used by the synchronization, the bias lock is in the absence of competition, the entire synchronization is eliminated, the CAS operation is not .
A biased lock will favor the first thread to get it, and if the lock is not fetched by another thread during the next execution, the thread that holds the biased lock will never need to be synchronized again .
by @sunhaiyu
2018.6.20
Java Virtual machines-thread safety and lock optimization