monitorenter与monitorexit指令主要和java并发关键字synchronization 在jvm层指令的实现有关系。
synchronization 方法的实现并没有采用这两个指令。
monitorenter主要是获取监视器锁,monitorexit主要是释放监视器锁。
Operation
Enter monitor for object
Description
The objectref must be of type reference
.
Each object is associated with a monitor. A monitor is locked if and only if it has an owner. The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref, as follows:
java中每个对象都关联着一个监视器。
If the entry count of the monitor associated with objectref is zero, the thread enters the monitor and sets its entry count to one. The thread is then the owner of the monitor.
If the thread already owns the monitor associated with objectref, it reenters the monitor, incrementing its entry count.
具有可重入性,当前线程获取了某一对象的监视器锁,再获取此对象监视器锁时,不用重新获取,只是增加对应的计数。
If another thread already owns the monitor associated with objectref, the thread blocks until the monitor's entry count is zero, then tries again to gain ownership.
Run-time Exception
If objectref is null
, monitorenter throws a NullPointerException
.
Notes
A monitorenter instruction may be used with one or more monitorexit instructions (§monitorexit) to implement a synchronized
statement in the Java programming language (§3.14). The monitorenter and monitorexit instructions are not used in the implementation of synchronized
methods, although they can be used to provide equivalent locking semantics. Monitor entry on invocation of a synchronized
method, and monitor exit on its return, are handled implicitly by the Java Virtual Machine's method invocation and return instructions, as if monitorenter and monitorexit were used.
对synchronized 方法没用这两个指令实现。
The association of a monitor with an object may be managed in various ways that are beyond the scope of this specification. For instance, the monitor may be allocated and deallocated at the same time as the object. Alternatively, it may be dynamically allocated at the time when a thread attempts to gain exclusive access to the object and freed at some later time when no thread remains in the monitor for the object.
The synchronization constructs of the Java programming language require support for operations on monitors besides entry and exit. These include waiting on a monitor (Object.wait
) and notifying other threads waiting on a monitor (Object.notifyAll
and Object.notify
). These operations are supported in the standard package java.lang
supplied with the Java Virtual Machine. No explicit support for these operations appears in the instruction set of the Java Virtual Machine.
Operation
Exit monitor for object
Description
The objectref must be of type reference
.
The thread that executes monitorexit must be the owner of the monitor associated with the instance referenced by objectref.
The thread decrements the entry count of the monitor associated with objectref. If as a result the value of the entry count is zero, the thread exits the monitor and is no longer its owner. Other threads that are blocking to enter the monitor are allowed to attempt to do so.
Run-time Exceptions
If objectref is null
, monitorexit throws a NullPointerException
.
Otherwise, if the thread that executes monitorexit is not the owner of the monitor associated with the instance referenced by objectref, monitorexit throws an IllegalMonitorStateException
.
Otherwise, if the Java Virtual Machine implementation enforces the rules on structured locking described in §2.11.10 and if the second of those rules is violated by the execution of this monitorexit instruction, then monitorexit throws an IllegalMonitorStateException
.
Notes
One or more monitorexit instructions may be used with a monitorenter instruction (§monitorenter) to implement a synchronized
statement in the Java programming language (§3.14). The monitorenter and monitorexit instructions are not used in the implementation of synchronized
methods, although they can be used to provide equivalent locking semantics.
The Java Virtual Machine supports exceptions thrown within synchronized
methods and synchronized
statements differently:
Monitor exit on normal synchronized
method completion is handled by the Java Virtual Machine's return instructions. Monitor exit on abrupt synchronized
method completion is handled implicitly by the Java Virtual Machine's athrow instruction.
When an exception is thrown from within a synchronized
statement, exit from the monitor entered prior to the execution of the synchronized
statement is achieved using the Java Virtual Machine's exception handling mechanism (§3.14).
Synchronization in the Java Virtual Machine is implemented by monitor entry and exit, either explicitly (by use of the monitorenter and monitorexit instructions) or implicitly (by the method invocation and return instructions).
For code written in the Java programming language, perhaps the most common form of synchronization is the synchronized
method. A synchronized
method is not normally implemented using monitorenter and monitorexit. Rather, it is simply distinguished in the run-time constant pool by the ACC_SYNCHRONIZED
flag, which is checked by the method invocation instructions (§2.11.10).
The monitorenter and monitorexit instructions enable the compilation of synchronized
statements. For example:
void onlyMe(Foo f) {
synchronized(f) {
doSomething();
}
}
is compiled to:
Method void onlyMe(Foo)
0 aload_1 // Push f
1 dup // Duplicate it on the stack
2 astore_2 // Store duplicate in local variable 2
3 monitorenter // Enter the monitor associated with f
4 aload_0 // Holding the monitor, pass this and...
5 invokevirtual #5 // ...call Example.doSomething()V
8 aload_2 // Push local variable 2 (f)
9 monitorexit // Exit the monitor associated with f
10 goto 18 // Complete the method normally
13 astore_3 // In case of any throw, end up here
14 aload_2 // Push local variable 2 (f)
15 monitorexit // Be sure to exit the monitor!
16 aload_3 // Push thrown value...
17 athrow // ...and rethrow value to the invoker
18 return // Return in the normal case
Exception table:
From To Target Type
4 10 13 any
13 16 13 any
The compiler ensures that at any method invocation completion, a monitorexit instruction will have been executed for each monitorenter instruction executed since the method invocation. This is the case whether the method invocation completes normally (§2.6.4) or abruptly (§2.6.5). To enforce proper pairing of monitorenter and monitorexit instructions on abrupt method invocation completion, the compiler generates exception handlers (§2.10) that will match any exception and whose associated code executes the necessary monitorexit instructions.
from:https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html#jvms-6.5.monitorenter