Mutex synchronization, lock optimization, and synchronized and volatile

Source: Internet
Author: User

Mutex synchronization

Mutex Synchronization (Mutual Exclusion & synchronization) is a common method of concurrency correctness assurance. Synchronization is a child. When multiple threads concurrently access shared data, the shared data is guaranteed to be used by only one (or some, when using semaphores) threads at the same time. While mutual exclusion is a means of realizing synchronization, the critical section (critial), mutex (mutex) and semaphore (Semaphore) are the main mutually exclusive implementations. Therefore, in these four words, mutual exclusion is the cause, synchronization is the fruit; mutual exclusion is the method, synchronization is the purpose.

The realization of synchronized

In Java, we all know that the Synchronized keyword is the most basic mutually exclusive synchronization means. Look at a simple code:

 Public Static void Main (string[] args) {    synchronized (testmain.  Class)    {            }}

This code is compiled after this:

1  Public Static voidMain (java.lang.string[]);2 Flags:acc_public, Acc_static3 Code:4stack=2, Locals=1, args_size=150:LDC #1//class Com/xrq/test53/testmain62: DUP73: Monitorenter84: Monitorexit95:returnTen linenumbertable: OneLine 7:0 ALine 11:5 - localvariabletable: - Start Length Slot Name Signature the0 6 0 args [ljava/lang/string;

The key is on lines 7th and 8th, after the source code is compiled, the Java virtual Opportunity uses the Monitorenter and Monitorexit bytecode directives to handle the Synchronized keyword.

According to the requirements of the virtual machine specification, when executing the monitorenter instruction, the first attempt is to get the lock of the object, if the object is not locked, or if the thread already has the lock of that object, and the lock counter is added 1, the lock counter will be reduced by 1 when executing the monitorexit instruction. , the lock is released when the counter is 0 o'clock. If an object lock fails, the current thread will block the wait until the object lock is freed by another thread.

About Monitorenter and Monitorexit, there are two points to pay special attention to:

1, synchronized synchronization block for the same thread is reentrant, there will be no lock yourself to the problem

2. The synchronization block will block the entry of the other threads after the entered thread has finished executing

Because Java threads are mapped to the native thread of the operating system, if you want to block or wake up a thread, you need the operating system to help complete, which requires a transition from the user state to the kernel mentality , so the state transition takes a lot of processor time, for the code simple synchronization block, The time that a state transition consumes may be longer than the time the user code executes, so synchronized is a heavyweight (heavyweight) lock In the Java language, and an experienced programmer will use it when it is really necessary.

By the way, look at the Hotspot virtual machine object header, Mark Word:

/tbody>
storage memory label Knowledge bit shape    
object hash, object generational age 01 unlocked
Pointer to lock record 00 lightweight locking
Pointer to heavyweight lock 10 inflation (heavyweight lock)
empty, no logging information required 11 GC tag
bias thread ID, biased timestamp, object generational age 01 can be biased to

See there is a heavyweight lock that refers to a heavyweight lock.

The implementation of volatile

For the volatile keyword, a variable that is modified by the volatile keyword, after generating assembly language, is roughly an extra instruction:

0x01a3de24:lock Addl $0x0, (%ESP)      ;.. f0830424 00

This operation is equivalent to a memory barrier, the memory barrier is not required when only one CPU accesses memory, but if there are two or more CPUs accessing the same piece of memory, and one is observing another, a memory barrier is required to ensure consistency. This directive "Addl $0x0, (%ESP)" (adding the value of the ESP register to 0) is obviously an empty operation (using this empty operation instead of the null instruction NOP is because the IA32 manual specifies that the lock prefix is not allowed with the NOP instruction), the key is the lock prefix, Query the IA32 manual, which is to make the cache of the CPU write memory, the write action will cause other CPUs or other cores to invalidate its cache, which is equivalent to a variable in the cache to do a "store and write" operation, so through such an empty operation , allowing changes to the previous volatile variable to be immediately visible to other CPUs.

Spin lock and self-adapting spin

Mutex synchronization, the most significant performance impact is the implementation of the blocking, suspending the thread and the operation of the recovery thread need to go to the kernel state to complete, these operations to the concurrency of the system has brought great pressure. At the same time, the virtual machine development team has noticed that in many applications, the locked state of shared data will only last for a short period of time, and it is not worthwhile to suspend and resume threads for this time. If there is more than one processor on the physical machine, allowing two or more threads to execute concurrently simultaneously, we can let the thread that requests the lock "Wait a moment", but not abandon the processor's execution time and see if the thread holding the lock will release the lock soon. In order for the thread to wait, we just have to let the thread perform a busy loop (spin), which is called a spin lock .

A spin lock has been introduced in JDK1.4.2, but it is closed by default. Spin can not replace blocking , and do not say the number of processors, the spin wait itself although the cost of the thread switching, but it is to occupy the processor time, so if the lock is occupied for a short time, the spin-wait effect is very good, conversely, if the lock is occupied for a long time, Then the spinning thread will simply consume the processor resources without doing any useful work, but will result in a waste of performance. Therefore, the optional wait must have a certain limit, if the spin exceeds the limit number of times still did not successfully obtain the lock, you should use the traditional way to suspend the thread, the default value of the spin number is 10.

Adaptive spin locks are introduced after JDK1.6. Adaptive means that the spin time is no longer fixed, but is determined by the time of the first spin on the same lock and the state of the owner of the lock. If the spin waits on the same lock object, and the thread holding the lock is running, the virtual machine will assume that the spin is likely to succeed again, and that it will allow the spin wait to last for a relatively longer period, such as 100 loops. In addition, if the spin is rarely successfully obtained for a particular lock, the spin process may be ignored in the future to avoid wasting processor resources. With the self-adaptive spin, as the program runs and the performance monitoring information continues to improve, the virtual machine to the program lock status prediction will be more and more accurate.

Lock removal

Lock elimination refers to the virtual machine instant compiler at run time, some code on the requirements of synchronization, but it is detected that there is no possibility of sharing the competition of the data to eliminate the lock. The main decision of the lock elimination is based on the support of escape analysis, if the judgment in a piece of code, all the data on the heap will not escape to be accessed by other threads, it can be treated as data on the stack, they are thread-private, synchronous lock nature does not need to do.

Lock coarsening

In principle, when we write code, it is always recommended to limit the scope of the synchronization block to as small as possible----only in the actual scope of the shared data to synchronize, so that the number of operations that need to be synchronized as small as possible, if there is a lock competition, the thread waiting for the lock will be able to get the lock as soon as possible.

In most cases, the above principles are correct, but if a series of successive operations are repeatedly locked and unlocked for the same object, even the lock operation appears in the loop body, even if there is no thread competition, frequent mutex synchronization operations can lead to unnecessary performance loss.

If this is not intuitive enough, then think of a piece of code repeatedly using StringBuffer's Append method to stitch the string example.

Mutex synchronization, lock optimization, and synchronized and volatile

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.