The login
registered
Write an article
Home page
Download the APP
Monitor mechanism in Java
beanlam
Monitor mechanism in Java
The concept of the monitor
Monitor, also known as Monitor in English, is often translated as “Monitor”. No matter Monitor is translated as “Monitor” or “Monitor”, it is obscure and cannot achieve an intuitive description of Monitor in Translated Chinese. The article “Operating System Synchronization Primitives” introduces some synchronization primitives supported by operating systems for process/thread synchronization. Semaphore semaphore and Mutex are the most important synchronization primitives. When using basic Mutex for concurrency control, the programmer needs to be very careful about controlling the down and up operations of mutex, otherwise problems such as deadlocks can easily occur. In order to make it easier to write correct concurrent programs, a higher level synchronization primitive named Monitor was proposed based on Mutex and Semaphore. However, it should be noted that the operating system itself does not support monitor. In fact, Monitor belongs to the category of programming languages. When you want to use Monitor, check whether the language itself supports monitor primitives. For example, C does not support Monitor, and the Java language does. The usual monitor implementation pattern is that the programming language provides syntactic sugar, but it is up to the compiler to implement the Monitor mechanism, which is what Java does.
An important feature of Monitor is that only one process/thread can enter a critical section defined in Monitor at any one time, which allows Monitor to achieve a mutually exclusive effect. However, it is not enough to have a mutex, and processes/threads that cannot enter the critical section of monitor should be blocked and woken up if necessary. Obviously, Monitor, as a synchronization tool, should also provide such a mechanism for managing process/thread state. Think about why we think Semaphore and Mutex are programmatically error-prone, because we need to manipulate variables ourselves and block and wake up processes/threads. The reason monitor is called a “higher level primitive” is that it inevitably needs to mask these mechanisms externally and implement them internally so that the user of Monitor sees a concise and easy-to-use interface.
Monitor base elements
The monitor mechanism requires several elements to work together:
- A critical region
- Monitor objects and locks
- Condition variables and wait, signal operations defined on monitor objects.
The main purpose of using the monitor mechanism is to mutually exclusive access to the critical region. In order to block the process/thread that cannot access the critical region, a Monitor object is required to assist. This Monitor object has the corresponding internal data structure, such as the list. To save blocked threads; And because the Monitor mechanism is essentially based on mutex primitives, the Monitor Object must also maintain a mutex-based lock. In addition, in order to block and wake up a process/thread at the appropriate time, a condition variable needs to be introduced that determines when the “appropriate time” is. This condition can come from the logic of the program code or from within the Monitor Object. In short, Programmers have a great deal of autonomy over the definition of conditional variables. However, because the Monitor Object uses internal data structures to hold blocked queues, it must also provide two apis to allow threads to block and then wake up, namely wait and notify.
Java language support for Monitor
Monitor is a high-level primitive provided by operating systems. However, its implementation pattern may vary from programming language to programming language. The following uses Java monitor as an example to explain how monitor is implemented in Java.
Delineation of critical regions
In Java, you can use the synchronized keyword to modify instance methods, class methods, and code blocks, as follows:
/**
* @author beanlam
* @version 1.0
* @date 2018/9/12
*/
public class Monitor {
private Object ANOTHER_LOCK = new Object();
private synchronized void fun1() {
}
public static synchronized void fun2() {
}
public void fun3() {
synchronized (this) {
}
}
public void fun4() {
synchronized (ANOTHER_LOCK) {
}
}
}
Copy the code
Methods and blocks of code that are modified by the synchronized keyword are the critical areas of monitor.
monitor object
Synchronized (this), ANOTHER_LOCK, ANOTHER_LOCK, ANOTHER_LOCK, ANOTHER_LOCK, ANOTHER_LOCK, ANOTHER_LOCK, ANOTHER_LOCK Synchronized is actually associated with this if it modifies an instance method, and this.class if it modifies a class method. In summary, synchronzied needs to be associated with an object, which is the Monitor Object. In the mechanism of Monitor, the Monitor Object plays the role of maintaining MUtex and defining the Wait/Signal API to manage blocking and awakening of threads. The java.lang.Object class in the Java language meets this requirement. Any Java Object can be used as a Monitor Object of the Monitor mechanism. Java objects are stored in memory in three parts: the object header, the instance data, and the alignment fill. In the object header, the lock identifier is stored. The java.lang.object class defines wait(), notify(), and notifyAll() methods. The implementation of these methods relies on ObjectMonitor, a C++ -based implementation of the JVM. The basic principle is as follows:
MonitorObject.png
When a thread needs to acquire an Object lock, it is placed in an EntrySet and waits. If the thread acquires the lock, it becomes the owner of the current lock. If, according to program logic, a thread that has acquired a lock lacks some external condition to proceed (for example, a producer finds the queue full or a consumer finds the queue empty), then the thread can call the wait method to release the lock and block in the wait set. Other threads at this point have the opportunity to acquire the lock and do other things, thereby making the previously untenable external condition true and allowing the previously blocked thread to re-enter the EntrySet to compete for the lock. This external condition is called a condition variable in the Monitor mechanism.
The synchronized keyword
Synchronized keyword is an important tool used by Java syntactic developers to facilitate multithreaded synchronization. To access a synchronized method modified method or block of code, the lock on the Object bound to the synchronized keyword is acquired. This lock also prevents other threads from accessing other synchronized code areas associated with the lock.
When analyzing the principle of synchronized in many articles and materials on the Internet, it is basically said that synchronized is realized based on monitor mechanism, but few articles are clear and vague. Referring to the basic elements of Monitor mentioned earlier, if synchronized is implemented based on the Monitor mechanism, what are the corresponding elements? It has to have a critical section, the critical section here we can think of as a P or V operation on the object header mutex, that’s a critical section what does the Monitor object correspond to? Mutex? The real Monitor object cannot be found. So I think that the statement that synchronized is implemented based on the monitor mechanism is incorrect and ambiguous. The Monitor mechanism provided by Java is actually formed by the cooperation of Object, synchronized and other elements, and even external condition variables are also a part of it. The underlying ObjectMonitor of the JVM is only a common pattern used to aid in implementing the Monitor mechanism, but most articles refer to ObjectMonitor directly as the Monitor mechanism. I think it should be understood this way: Java’s support for Monitor is provided to developers at a mechanistic granularity, meaning that developers use a combination of the synchronized keyword and elements such as wait/notify for Object, Only then can they say that they use monitor mechanism to solve a producer-consumer problem.
Check out my wechat public account