Synchronized is a common locking mechanism in Java, and synchronized+Object.wait/notify is a common wake-up mechanism. Synchronized and Object.wait/notify are examples of synchronized and object. wait/notify
- Synchronized lock upgrade.
- How synchronized works.
- How synchronized and wait queues work together.
- Why Object. Wait must be synchronized
Synchronized implementations in the JVM implement method synchronization and code block synchronization based on entering and exiting Monitor objects. The Monitor Enter directive is inserted at the start of the synchronized code block after compilation, while the Monitor exit directive is inserted at the end of the method and at the exception. The JVM must ensure that each Monitor Enter has a corresponding Monitor exit paired with it. Any object has a Monitor associated with it, and when a Monitor is held, it is locked.
Java 1.6 in order to reduce consumption for the performance of the locks and the lock is released, the introduction of the “biased locking” and the “lightweight” lock, in Java SE 1.6, lock a total of 4 kinds of state, the level is from low to high in turn: unlocked state, biased locking state, lightweight and heavyweight lock state lock, this a few state as competition situation gradually upgrade.
Note that synchronized can modify a method as well as an object.
If the monitor Enter command fails to acquire the lock, the thread is added to the SynchronizedQueue of the monitor object. When the thread occupying the monitor object executes monitor out, the thread in the synchronization queue is awakened.
So the question is, which thread on the synchronization queue should you choose to wake up? By default, Java8 selects the thread that was recently added to the synchronization queue. This can be verified using the following code:
private static Object obj = new Object();
public static void main(String[] args) throws Exception {
synchronized (obj) {
newThread("t1");
newThread("t2");
newThread("t3");
newThread("t4");
newThread("t5");
Thread.sleep(1000);
System.out.println("main release");
}
System.out.println("main end");
Thread.sleep(2000);
}
private static void newThread(String name) throws Exception {
new Thread(() -> {
synchronized (obj) {
System.out.println(Thread.currentThread().getName() + " get");
}
}, name).start();
Thread.sleep(100L);
}
Copy the code
The output is:
Synchronization queues and wait queues
Now that you know the basic concepts of synchronized, let’s look at object.wait ()/notify(). A Monitor Object contains a synchronization queue (consisting of _CXq and _EntryList) and a wait queue (_WaitSet).
- The queue to be added according to the policy when the notify or notifyAll wakes up (policy defaults to 0)
- Wake up the next thread according to QMode policy when exiting synchronized block (QMode defaults to 0)
Note: Synchronized synchronization queue and wait queue are similar to those based on AQS (Lock /condition), except that the former is a synchronization queue corresponding to a wait queue, while the latter is a synchronization queue corresponding to multiple wait queues.
The flow chart of synchronized synchronization queue and wait queue is as follows:
So far, we’ve had an overview of how synchronized works and how its synchronization and wait queues work together.
Finally, we consider two questions:
Object. Wait /notify: synchronized can’t block a thread and wake it up with another thread.
Object. Wait /notify: Synchronized
Take a break and think about the reasons for these two questions.
With regard to the first question, synchronized is used only for simple adding and unlocking, while Object.wait/notify is used to implement the logic of being notified and then performing the next action. Object. Wait is meaningless if there is no logic behind object. wait.
As for the second question, why must synchronized be used? We all know that the purpose of synchronized locking is to ensure atomicity, so we have reason to believe that the reason here is mostly atomicity. So atomicity for what? To ensure atomicity of adding the current thread to the _WaitSet wait queue and monitoring out to wake up other threads when object. wait. To ensure that the thread state associated with the lock does not change when the current thread is moved from WaitSet to the synchronization queue when Object.notify.
Recommended reading
- The states of Java threads
- How to gracefully print ABC from 3 threads
- DDD domain concepts
- How to solve the problem of large paging query
- From intrusive Service governance to Service Mesh
- Blah blah blah, service governance is what