Java synchronization lock

  1. Synchronized keyword can be used to lock methods and code blocks
  2. Synchronized locks are implicit locks built into the JVM (as opposed to locks, which implicitly Lock and release)
  3. The implementation of Synchronized lock depends on the operating system. System calls to obtain and release the lock will cause switching between user mode and kernel mode
  4. Jdk1.5 can only use synchronized to Lock, 1.6 introduced Lock (request Lock based on Java implementation, explicit Lock and release, better performance)
  5. Synchronzied synchronk1.6 introduces the concepts of biased, lightweight, and heavyweight locking for Synchronzied.
  6. With synchronized or Lock, thread context switching is unavoidable
  7. One of the performance optimizations of Lock over synchronized is that Lock acquisition does not cause a user-kernel switch when a thread is blocked, whereas synchronized does (see point 3). But thread blocking causes context switching (see point 6)
  8. Java threads block and wake up depending on operating system calls, resulting in user-kernel switching

This article focuses on upgrading synchronized locks.

A synchronized synchronous lock

Java object head

Each Java object has an object header, which consists of a type pointer and a tag field. On a 64-bit VM, the compressed pointer is disabled, the flag field is 64-bit, and the type pointer is 64-bit, and the total length is 16 bytes. The lock type information is the last two bits of the marker field: 00 indicates a lightweight lock, 01 indicates no lock or biased lock, and 10 indicates a heavyweight lock. If the third-to-last bit is 1, biased locking is enabled for the class, and 0, biased locking is disabled for the class. The following figure, photograph wiki:wiki.openjdk.java.net/display/Hot…

The left column indicates bias lock enabled (box 1) and the right column indicates bias lock disabled (box 3). Both 1 and 3 indicate the initial state of no lock. If biased lock is enabled, the lock upgrade step should be 1->2->4->5. If biased lock is disabled, the lock upgrade step is 3->4->5.

The left column indicates bias lock enabled (box 1) and the right column indicates bias lock disabled (box 3). Both 1 and 3 indicate the initial state of no lock. If biased lock is enabled, the lock upgrade step should be 1->2->4->5. If biased lock is disabled, the lock upgrade step is 3->4->5.



There are several additional parameters for biased locking:



Note BiasedLockingStartupDelay parameter, the default value is 4000 ms, said the virtual machine startup latency of 4 s will only be used to lock (lock) using lightweight first.

Biased locking

The lock-biased scenario is one in which only the same thread requests the lock most of the time, and no multiple threads compete for the lock. When a thread is locked for the first time, the JVM uses cas to set the current thread address to the thread ID marker, the last three bits being 101. The next time the same thread obtains the lock, it only needs to check whether the last three bits are 101, whether it is the current thread, and whether the epoch is the same as the epoch of the lock object’s class.

The performance improvement brought by biased lock optimization refers to avoiding the switch between user state and kernel state caused by the system call to acquire the lock. Because the same thread obtains the lock, there is no need to make the system call every time to acquire the lock.

If the current thread when acquiring the lock (unlocked state) thread ID does not match with the current thread, biased locking will be revoked, back to the current thread, if to reach BiasedLockingBulkRebiasThreshold value, the default 20 times, the current class of biased locking fails, changes is, the value of the epoch, If the epoch value of the locked class is increased by 1, the subsequent lock object will copy the epoch value of the class to the EPOCH marker bit in the diagram. If the value of the total cancellation number reach BiasedLockingBulkRevokeThreshold 40 times (the default), will disable the current class of biased locking, the object is first on the right side column, direct lighter weights lock lock began (lock the upgrade).

The cancellation of biased lock is a very troublesome process, which requires all threads to reach the safe point (STW), traverse the thread stack of all threads to check whether they hold lock objects, avoid lock loss, and process the epoch.

If there is multi-threaded contention, then biased locks need to be upgraded to lightweight locks.

Lightweight lock

Lightweight lock processing is a scenario where locks are requested by different threads at different times (threads are executed alternately). Even if there are multiple threads competing for the lock at the same time, the thread that obtains the lock holds the lock for a very short time and releases the lock very soon.

Thread locking, judge not lock, will open up a space in the current thread stack, as a lock, lock object head tag field copied (copied is to do a record, because behind to lock head mark the value of the field to replace object to just copy the tag field space address Just like the pointer to lock record part in the object header, the last 2 bits are 00 because of memory alignment. Then based on the CAS operation, the address of the copy lock record is set to the value of the marker bit of the lock object header. If successful, the lock is obtained. If the last two digits are not 01 (from the bias lock or no lock state), the lock is already held by a thread. If it is used by the current thread (requiring reentrant), set a 0. This is a stack structure. When the lock is finally released, the last element records the value of the original marker field of the lock object, and then sets it to the lock object header through CAS.

Note that when the CAS fails to acquire the lock, the current thread will spin for a certain number of times to upgrade to the heavyweight lock, and the current thread will block.

Heavyweight lock

Heavyweight is what is commonly referred to as the added synchronous lock, which is Java’s basic lock implementation. The system call is made to acquire and release the lock, resulting in a context switch.

About spin locks

About the spin lock, I looked up the relevant information, there are two main explanations: 1. The lightweight lock fails to compete, it does not immediately expand to heavyweight, but spins a certain number of times to try to obtain the lock; 2. 2, is the heavyweight lock competition failure will not block immediately, but also a certain number of spins (here involves a self-tuning algorithm). About the specification, or to look at the source of the JVM implementation to be sure, this is jdk8 implementation: hg.openjdk.java.net/jdk8/jdk8/h…

Print bias lock parameters

As follows: – XX: XX: + UnlockDiagnosticVMOptions – + PrintBiasedLockingStatistics me in the circulation of the main method to obtain the same lock, print the results are as follows:

    public static void main(String[] args) {
        int num = 0;
        for (int i = 0; i < 1 _000_000000; i++) {
            synchronized(lock) { num++; }}}Copy the code