Synchronized usage

In Java, the simplest and most crude means of synchronization is the keyword synchronized. Synchronized instance method, the lock is the current instance object ②. Synchronized class method, the lock is the current class object ③. The lock is an example of an object in parentheses:

Public class SynchronizedTest */ synchronized void test() {} public synchronized void test() {} */ public synchronized static void test1() {} /** * public void test2() {// synchronized Synchronizedtest.class) {// Synchronized (this) {}}}}Copy the code

Synchronized implementation

Javap -verbose Displays the preceding example:



Synchronized methods






Synchronized code block






    case Bytecodes::_monitorenter:
    {
      pop_object();
      set_monitor_count(monitor_count() + 1);
      break;
    }
  case Bytecodes::_monitorexit:
    {
      pop_object();
      assert(monitor_count() > 0, "must be a monitor to exit from");
      set_monitor_count(monitor_count() - 1);
      break;
    }
    
    void      pop_object() {
      assert(is_reference(type_at_tos()), "must be reference type");
      pop();
    }
    
    void      pop() {
      debug_only(set_type_at_tos(bottom_type()));
      _stack_size--;
    }
    int         monitor_count() const  { return _monitor_count; }
    void    set_monitor_count(int mc)  { _monitor_count = mc; }
Copy the code

From the source code we find that when the thread acquires the object lock, the counter is increased by one, and releasing the lock decreases the counter by one.

Monitor

Each object has its own monitor, when this object by the synchronized block or the object synchronization method invoked, execution method of the thread must first obtain the object of the monitor can enter the synchronized block and synchronization method, if there is no access to monitor the thread will be BLOCKED at the entrance of the synchronized block and synchronization method, into the BLOCKED state, as shown in figure:

Monitor is a thread-private data structure, and each thread has a list of available Monitor Records, as well as a global list of available records. Each locked object is associated with a Monitor (the LockWord in the MarkWord of the object header points to the start address of the monitor), and an owner field in the Monitor stores the unique identification of the thread that owns the lock, indicating that the lock is occupied by the thread. Its structure is as follows:

Owner: The initial value is NULL, indicating that no thread owns the monitor Record. When the thread successfully owns the lock, the unique identifier of the thread is saved. When the lock is released, it is set to NULL EntryQ: RcThis: represents the number of threads blocked or waiting on the monitor Record. Nest: represents the number of threads blocked or waiting on the Monitor Record. HashCode: Holds the HashCode value (and possibly GC age) copied from the object header Used to avoid unnecessary obstruction or waiting thread to wake up, because each time only one thread can have lock, if every time a lock is released before the thread wakes up all threads that are being blocked or wait for, will cause unnecessary context switch (from blocking to ready then lock failure because competition is blocked) resulting in serious decline in performance. Candidate has only two possible values: 0 means there are no threads to wake up and 1 means a successor thread to wake up to compete for the lock

Lock the optimization

Synchronization in JDK1.6 is implemented with various optimizations, such as adaptive spin, lock elimination, lock coarser, lightweight lock and biased lock, and mainly solves three scenarios: ①. Only one thread enters the critical section, biased locking ②. Multiple threads do not compete, lightweight locking ③. Multi-thread competition, heavyweight lock bias lock → lightweight lock → heavyweight lock process, the lock can be upgraded but not degraded, this strategy is to improve the lock and release lock efficiency, source code analysis can be seen accounted for a small Wolf – synchronized implementation

Biased locking

The purpose of introducing biased locks is to minimize unnecessary lightweight lock execution paths without multi-threaded contention. Compared with lightweight locks, biased locks only rely on one CAS atomic instruction to replace ThreadID. However, in case of multiple threads competing, biased locks must be revoked, mainly verifying whether biased locks, lock identifier bits and ThreadID are used.

  • lock











  • There is no executing code at this point in time








  • unlock







  • Lightweight lock

    The main purpose of introducing lightweight locks is to reduce the performance cost of traditional heavy locks using operating system mutex without multithreading competition. If multiple threads enter the critical zone at the same time, the lightweight lock will expand and upgrade the heavyweight lock, so the emergence of the lightweight lock is not to replace the heavyweight lock. In the case of multiple threads competing, the lightweight lock is slower than the weight lock.

  • lock
















  • unlock

  • If the Mark Word of the object still points to the lock record of the thread, execute ② ②. Replace the product of the product’s product with CAS operation and the product of the product copied in the thread. If the product is successful, it indicates that the lock is released successfully. Otherwise, execute ③ ③. If the CAS operation fails to be replaced, it indicates that another thread is trying to obtain the lock. In this case, the suspended thread must be woken up when the lock is released

    Heavyweight lock

    The heavyweight Lock is implemented through the internal monitor of the object. The essence of the monitor is the Mutex Lock implementation of the underlying operating system. The switching between the threads of the operating system needs to switch from the user state to the kernel state, and the switching cost is very high.

    Thank you

    Impressed source code — synchronized implementation principle “deep understanding of Java VIRTUAL machine” “Java concurrent programming art”