Java multithreading synchronized bottom-level implementation

Source: Internet
Author: User

have been trying to understand the underlying implementation of this particularly important keyword. (Of course now also not fully understand, if there are errors later modified this article)

First of all, this keyword synchronize can be said to be a grammatical sugar, its specific usage on the Internet a lot of blogs are relatively clear.

Simply put, "lock" an object. First, the object to find a place is not necessarily the instance object of the class inside the heap, or the class object of the method area. Second, the keyword modified code block lock process has two, enter the time to try to obtain a lock (Java bytecode monitorenter), exit the Lock (Java bytecode monitorexit). The next layer of the two operations is lock () and Unluck () based on the mutex lock.

The specific implementation of these two functions is provided by the operating system. The lock () operation is "get Lock" "lock" "Enter critical section", etc., and so on, different places describe inconsistency. Its specific process is to view a semaphore (held by this lock) to see if the lock is currently available, if it can be obtained directly, and modify the value of the semaphore (for example, change 1 to 0). If not, put the thread that is requesting the lock into a queue by itself, which specifically puts the thread "trapped" on the object (the lock) and then blocks the thread itself. The unlock () operation is "release lock" "Unlock" "Leave critical section". He can directly modify the value of the semaphore. At the same time he sees if there is a process "trapped" on this object (lock). If there is, wake it into the ready queue. (The specific implementation of the semaphore is different, the recorded signal volume can be more convenient to understand the process). These basic operations are, of course, atomic in nature.

This place also has a very important point, lock, Thread, object how exactly these 3 things are connected together. To understand this, we have to say that the lock is not necessarily a heavyweight "mutex" provided by the operating system. There is also a lock: lightweight lock. This lock is a run-time optimization that can be used directly if the code block decorated with synchronize does not have concurrency behavior.

At first, be aware of Mark Word. This is an area of 32bit or 64bit (determined by the JVM) in the object header of each object (called Mark Word, the object header, and an area as large as it holds a pointer to the class object of the method area). Some data, such as hash code, GC generational age, lock mark, and so on, are saved during the operation of the object. Its existence is necessary because there are indeed some run-time information to be retained in this form. A thread finds a locked object based on Java bytecode, looks at the lock flag, checks to see if a lock has been acquired by another thread, or, if not, creates a lock record in the stack frame of the thread (the lock record, in some places called the Monitor record), and saves this mark A copy of Word, and then point to the object with an owner pointer. The object directly changes mark Word to a pointer to the lock record. (Remember that the size of Mark Word is exactly the same size as the current operating system pointer, so you can change it without the need for a fill)

But this place I don't understand at first, why do I have to go around like this? Since the lock is on top of the object, why not just keep a space in the object header, record or the "lock" thread, such as with the thread ID or internal identifier. Each time the thread enters the critical section, the object is accessed directly to the object head to see if the value is itself this thread, if not blocking itself.

The reason: The object header is very precious, because each object has, although it is necessary, but its content is really not the actual content of the object itself. That means you have to do everything you can to narrow it down otherwise it's inefficient (imagine that you have a space where more than half stores some assorted information). The runtime program stack is a very broad space compared to the object's head. A treasure of this space is not a matter of this space. This allows the storage space to be optimized just by "multiplexing". Use the extra space that you would otherwise need to store directly with Mark Word and throw its original value to the thread's stack. This double benefit the thread that holds the lock on the object, and does not lose Mark Word (anyway, I'm not afraid to find it with the pointer pointing to the thread). The thread then uses a pointer, owner, to point to the object. It's perfect.

Is this a lightweight approach to locking, if not lightweight? In fact, the JVM's optimization strategy ensured that he was initially treated as lightweight (the JVM's optimization strategy has spin locks, lock removal, lock coarsening, lightweight locks, bias locks, etc.). This place also explains 2 points, first, what the benefits are, and second, why you can do so. Thirdly, why do you do this?

First, if the mutex that is provided directly with the operating system locks the mutex, it will use the operating system call, from the user state to the kernel mentality, the overhead is very high. In this way (a lightweight lock) is just a cost of a CAS operation (to ensure its atomicity). Second, right now. If a lightweight lock is useless (that is, a competitor is trying to take the lock), it can "swell" into a heavyweight lock (Mutex lock) directly. Third, the reality is that many synchronize-modified code actually does not compete in the actual operation of the situation, so that the operation of the direct reduction of a lot of overhead.

And then, under what circumstances would it swell from a lightweight to a heavyweight mutex lock? In fact, this part of the JVM optimization, first "think" this locking and most of the situation did not compete, so first "witty" to use lightweight, this time if there is competition, that is, there are other threads trying to obtain a lock, it is "inflated" to a heavyweight. More specifically, the other thread calls lock (), discovering that the current object's object header's flag bit is "lightweight lock." It goes to see owner again, if it is a "re-entry". If not, then the competition, then the "expansion". This is the first possible, that is, a line enters upgradeable in the run, after a join occurs swell. In fact, there is a second possibility, occurred in the previous line Cheng Gang lock, this time all threads are considered unlocked, at the same time through the CAS competition, one will succeed, others will fail, so also expand.

Then the expansion process. First, change the state value of the object lock flag and point the pointer saved in Mark Word to the mutex lock (of course, the content of Mark Word is still not lost) I'm looking at a deep understanding of the Java Virtual Machine book, plus some blogs on the web. I didn't make this part clear, this place i " guess ": Invoke an operating system mutex, generate a mutex, and point the value of Mark Word to it. At the same time, let this mutex or some other data structure and way to save Mark Word's original run-time information. This place of the mutex lock may be really true "heavyweight" lock, its specific implementation I estimate and recorded signal volume of the PV primitive operation is similar, but also to retain some flags store owner, re-enter the number, waiting for the number of queue elements, waiting for the queue pointer, If the current release lock is a thread that requires wake-up information.

The above content guarantees that the correct mark word points to a mutex Lock. After this, the process is to call lock () to try to access the critical section, the first object head point to a lock, and then into the lock found that the lock has been locked and not owner, so he blocked himself. Out of the critical section to wake up other blocking threads. There's nothing to say.

Java multithreading synchronized bottom-level implementation

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.