Pessimistic concurrency policy-Synchronized mutex lock and synchronized mutex
Since volatile is not enough to guarantee data synchronization, a lock must be introduced to ensure it. Mutex lock is the most common synchronization method. When multiple threads compete for the same shared data during the concurrent process, it ensures that only one thread can use the shared data at the same time, other threads can compete again only after the lock is released. For java developers, we are most familiar with the lock function by using the synchronized keyword. When multithreading concurrency is involved, for some variables, you should not hesitate to add synchronized to ensure the synchronization of variables.
In C/C ++, you can directly use the mutex lock provided by the operating system to implement synchronization and thread blocking and wakeup. In contrast, java needs to encapsulate these underlying layers, synchronized is a typical mutex lock, and it is also a JVM-Level Lock. Its implementation details are all encapsulated in the JVM implementation, and developers only provide the synchronized keyword. Based on the lock granularity, synchronized can be used to lock a variable, a method, an object, and a class. After the program block modified by synchronized is compiled, two bytecode commands, monitorenter and monitorexit, will be generated before and after compilation, which involve the determination of locking and unlocking objects. This depends on synchronized, if the specified object is specified, such as synchronized (variable) and synchronized (this), it indicates that the unlocked object is a variable or runtime object. If the object is not explicitly specified, the corresponding lock object will be searched based on the synchronized modification method. If a non-static method is modified, the object corresponding to this method will be the Lock Object, if you modify a static method, the class object corresponding to this method is the lock object. When an object is locked, all the methods in the object modified with synchronized will be blocked, and non-synchronized methods in the object can be called normally without affecting the lock.
To implement mutex lock, the JVM's monitorenter and monitorexit bytecode are implemented based on the mutex lock of the underlying operating system. The java-level threads are mapped to the native threads of the operating system, at this time, if you want to block or invoke a thread, you need the assistance of the operating system. This requires switching from the user State to the kernel state for execution. This switching is very expensive, it takes a lot of processing time. If possible, such a switchover should be reduced. jvm generally takes some measures for optimization. For example, before blocking the thread, let the thread spin and wait for a while, other threads may have been unlocked during the waiting period. In this case, the thread does not need to be blocked to avoid switching from the user State to the kernel state.
Synchronized has another important feature-reentrant. This feature is mainly for the current thread. Re-entry means that you can obtain your internal lock again. If the current thread already has the lock for this object when trying to obtain the object lock, when the lock counter is added, the lock is released by one. When the lock counter is 0, the lock is completely released. At this time, other threads can lock the lock. The reentrant feature is used to lock itself, as shown in the following pseudocode:
Public class DeadLock {
Public synchronized void method1 (){}
Public synchronized void method2 (){
This. method1 ();
}
Public static void main (String [] args ){
DeadLock deadLock = new DeadLock ();
DeadLock. method2 ();
}
}
This is actually not uncommon. the synchronous method in a class calls another synchronous method. If synchronized does not support re-entry, the current thread will try to obtain the lock of the deadLock object when entering the method2 method, when the method1 method is executed in the method2 method, the current thread will attempt to obtain the lock of the deadLock object. At this time, because re-entry is not supported, it will wait for the lock release of the deadLock object, block yourself. This is how you lock yourself. Therefore, the introduction of the re-import mechanism eliminates this situation.
Synchronized implements an unfair lock, which is mainly manifested in the action of obtaining the lock. It does not assign a lock to the waiting thread before and after the lock application time, every time a lock is released, any thread will have the opportunity to compete for the lock. The purpose of this operation is to improve the execution performance, and of course thread hunger will also occur.
The last feature (disadvantage) of synchronized is non-disruptive. Among all the waiting threads, the only thing you can do is wait. The actual situation may be that some tasks have been waiting for long enough, I want to cancel this task to do other things. At this time, synchronized cannot be implemented for you. It gives all implementation mechanisms to JVM, while providing convenience, it also reflects its own limitations.
This section mainly introduces the synchronized Keywords of java, including its role and the underlying implementation of JVM and the operating system. It is reentrant and non-disruptive, it implements an unfair mutex lock, and it is also a pessimistic concurrency policy. No matter whether there is competition or not, any data operations must be locked. A deep and comprehensive understanding of synchronized is helpful for understanding the modules related to multi-thread concurrency in tomcat.
(Java-related) which keyword can be used to apply a mutex lock to an object?
Synchronized
In the chapter of thread security and Synchronization
1. Which of the following keywords can apply the mutex lock A serialize B synchronized C transient D static to the object?
Answer: B
A: serializing objects
C: Attributes modified by the keyword transient will not be serialized.
D: static