The underlying principles of synchronized are closely related to Monitor

1. Java objects

The following uses a 32-bit VM as an example

The types of objects, such as Student or Teacher, are represented by KlassWord, which is a pointer to the Class to which the object belongs. Find the class.

Where the Mark Word structure is

Where, age represents the generational age of garbage collection, which can be seen in the generational collection algorithm. After a certain age, they were transferred from the survivor zone to the old age. The last two, biASed_lock and 01, represent biased locking and locked states. Others show what each represents in different states. Normal Indicates the Normal status of an object. Its value usually changes when you add various variables to it. The array object

Note: So, here we can also think of an Integer object holding 8 bytes of object headers and 4 bytes of int data.

The total is 12 bytes, while the basic int takes only 4 bytes. In memory sensitive cases, basic types are recommended. Each Java object can be associated with a Monitor object, If an object is locked (heavyweight) with synchronized, a pointer to the Monitor object is set in the Mark Word of the object header

When we execute the following code on thread 2:

Synchronized (this){// synchronized(this)Copy the code

1. When the Thread2 thread executes the above code, the current object this will be locked, which is a heavyweight lock. The MarkWord field of this object header points to the reference address of the Monitor object created by the operating system. Once the lock is acquired, it tries to find a Monitor to associate with it, changes the last two bits, the tag bit, from 01 to 10, and changes all the preceding bits to Pointers to monitor objects, occupying 30 bits. Since there are only Thread2 threads at this point, the lock was successfully acquired. Of course, you become the owner of the Monitor object. Owner represents the owner of the Monitor lock, and there can only be one owner at a time

2. The Monitor object can have only one owner. If thread3 or Thread4 want to acquire the lock, the Monitor object must enter the blocked queue EntryList and wait for Thread2 to release the lock. EntryList can be understood as a bit blocking queue or wait queue. Wait until another thread releases ownership of the owner

3. After the lock resources are released, ThREAD-3 and Thread-4 compete with each other for lock resources. The CPU decides who can obtain the lock.

4. The WaitSet of the Monitor object holds the thread that has acquired the lock, but the thread is in Waiting for some other reason, and the lock resource is released

1. At first, the Owner of Monitor is null

2. When Thread-2 executes synchronized(obj), the Owner of Monitor is set to Thread-2. Monitor can only have one Owner

3. When Thread-2 is locked, the EntryList BLOCKED is entered if thread-3, Thread-4, and Thread-5 also execute synchronized(obj)

Thread-2 executes the contents of the synchronized code block and wakes up the waiting threads in the EntryList to compete for the lock. The competition is unfair

5. In the figure, Thread-0 in WaitSet is the Thread that has acquired the lock before but is not in WAITING state, which will be analyzed in wait-notify later

Synchronized must be a monitor entering the same object to have this effect

Objects that are not synchronized do not associate monitors and do not follow the above rules

3. Understand the underlying working principle of synchronized from the perspective of bytecode

public class synchronized1 { static final Object lock=new Object(); static int counter=0; public static void main(String[] args){ synchronized (lock){ counter++; }}}Copy the code

For details about the decompiling process and the bytecode instructions, see JVM Learning – bytecode instructions:

public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: Getstatic #2 //<-lock (synchronized) 3: dup 4: astore_1 //lock reference ->slot1 5: Monitorenter // Set lock Markword to monitor pointer 6: getstatic #3 // Field counter:I 9: iconST_1 10: iadd 11: Putstatic #3 // Field counter:I 14: aload_1 //<-lock Monitorexit // Resets the lock object MarkWord to wake up EntryList. Resets other MarkWord fields to allow waiting threads in EntryList to compete for lock 16: Goto 24 /* If an Exception occurs in a synchronized code block, then the following lines are processed, i.e., lines 19-23. Restore the state in Monitor and wake up the other threads in entryList */ 19: astore_2 20: aload_1 21: monitorexit 22: aload_2 23: athrow 24: return Exception table: from to target type 6 16 19 any 19 22 19 anyCopy the code

Four things to watch ❤️

If you find this article helpful, I’d like to invite you to do three small favors for me:

  1. Like, forward, have your “like and comment”, is the motivation of my creation.

  2. Follow the public account “JavaAC” to share original knowledge from time to time.

  3. Also look forward to the follow-up article ing🚀

  4. Pay attention to the scan code to obtain the learning materials package