synchronized关键字底层c++代码调用
编译完如下java代码后
public class JolDemo {
public static void main(String[] args) throws InterruptedException {
A a = new A();
synchronized (a) {
System.out.println(a);
}
}
}
查看下其编译后的bytecode
0 new #2 <com/it/sun/course/A>
3 dup
4 invokespecial #3 <com/it/sun/course/A.<init>>
7 astore_1
8 aload_1
9 dup
10 astore_2
11 monitorenter
12 getstatic #4 <java/lang/System.out>
15 ldc #5 <synchronized>
17 invokevirtual #6 <java/io/PrintStream.println>
20 aload_2
21 monitorexit
22 goto 30 (+8)
25 astore_3
26 aload_2
27 monitorexit
28 aload_3
29 athrow
30 return
我们看到11行的指令monitorenter表示进入了sychronized同步代码块中,21行和27行的指令monitorexit表示退出了同步方法的执行。这里执行两次退出操作,猜测一下:21行是正常的退出,27行是在出现异常后执行的锁退出,避免造成死锁
moniterenter—指令 方法文件:src/hotspot/share/interpreter/interpreterRuntime.cpp
monitorenter调用时,所执行的方法
JRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, BasicObjectLock* elem))
#ifdef
thread->last_frame().interpreter_frame_verify_monitor(elem);
#endif
if (PrintBiasedLockingStatistics) {
Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
}
Handle h_obj(thread, elem->obj());
assert(Universe::heap()->is_in_or_null(h_obj()),
"must be NULL or an object");
ObjectSynchronizer::enter(h_obj, elem->lock(), CHECK);
assert(Universe::heap()->is_in_or_null(elem->obj()),
"must be NULL or an object");
#ifdef ASSERT
thread->last_frame().interpreter_frame_verify_monitor(elem);
#endif
JRT_END
monitorexit—指令 方法文件:src/hotspot/share/interpreter/interpreterRuntime.cpp
monitorexit调用时,所执行的方法
JRT_LEAF(void, InterpreterRuntime::monitorexit(BasicObjectLock* elem))
oop obj = elem->obj();
assert(Universe::heap()->is_in(obj), "must be an object");
// The object could become unlocked through a JNI call, which we have no other checks for.
// Give a fatal message if CheckJNICalls. Otherwise we ignore it.
if (obj->is_unlocked()) {
if (CheckJNICalls) {
fatal("Object has been unlocked by JNI");
}
return;
}
ObjectSynchronizer::exit(obj, elem->lock(), Thread::current());
// Free entry. If it is not cleared, the exception handling code will try to unlock the monitor
// again at method exit or in the case of an exception.
elem->set_obj(NULL);
JRT_END
ObjectSynchronizer::enter—函数 文件方法:src/hotspot/share/runtime/synchronizer.cpp
void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, TRAPS) {
if (DiagnoseSyncOnPrimitiveWrappers != 0 && obj->klass()->is_box()) {
handle_sync_on_primitive_wrapper(obj, THREAD);
}
if (UseBiasedLocking) {
if (!SafepointSynchronize::is_at_safepoint()) {
BiasedLocking::revoke(obj, THREAD);
} else {
BiasedLocking::revoke_at_safepoint(obj);
}
}
markWord mark = obj->mark();
assert(!mark.has_bias_pattern(), "should not see bias pattern here");
if (mark.is_neutral()) {
// Anticipate successful CAS -- the ST of the displaced mark must
// be visible <= the ST performed by the CAS.
lock->set_displaced_header(mark);
if (mark == obj()->cas_set_mark(markWord::from_pointer(lock), mark)) {
return;
}
// Fall through to inflate() ...
} else if (mark.has_locker() &&
THREAD->is_lock_owned((address)mark.locker())) {
assert(lock != mark.locker(), "must not re-lock the same lock");
assert(lock != (BasicLock*)obj->mark().value(), "don't relock with same BasicLock");
lock->set_displaced_header(markWord::from_pointer(NULL));
return;
}
// The object header will never be displaced to this lock,
// so it does not matter what the value is, except that it
// must be non-zero to avoid looking like a re-entrant lock,
// and must not look locked either.
lock->set_displaced_header(markWord::unused_mark());
// An async deflation can race after the inflate() call and before
// enter() can make the ObjectMonitor busy. enter() returns false if
// we have lost the race to async deflation and we simply try again.
while (true) {
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_monitor_enter);
if (monitor->enter(THREAD)) {
return;
}
}
}
ObjectSynchronizer::exit—函数 文件方法:src/hotspot/share/runtime/synchronizer.cpp
void ObjectSynchronizer::exit(oop object, BasicLock* lock, TRAPS) {
markWord mark = object->mark();
// We cannot check for Biased Locking if we are racing an inflation.
assert(mark == markWord::INFLATING() ||
!mark.has_bias_pattern(), "should not see bias pattern here");
markWord dhw = lock->displaced_header();
if (dhw.value() == 0) {
// If the displaced header is NULL, then this exit matches up with
// a recursive enter. No real work to do here except for diagnostics.
#ifndef PRODUCT
if (mark != markWord::INFLATING()) {
// Only do diagnostics if we are not racing an inflation. Simply
// exiting a recursive enter of a Java Monitor that is being
// inflated is safe; see the has_monitor() comment below.---
assert(!mark.is_neutral(), "invariant");
assert(!mark.has_locker() ||
THREAD->is_lock_owned((address)mark.locker()), "invariant");
if (mark.has_monitor()) {
// The BasicLock's displaced_header is marked as a recursive
// enter and we have an inflated Java Monitor (ObjectMonitor).
// This is a special case where the Java Monitor was inflated
// after this thread entered the stack-lock recursively. When a
// Java Monitor is inflated, we cannot safely walk the Java
// Monitor owner's stack and update the BasicLocks because a
// Java Monitor can be asynchronously inflated by a thread that
// does not own the Java Monitor.
ObjectMonitor* m = mark.monitor();
assert(m->object()->mark() == mark, "invariant");
assert(m->is_entered(THREAD), "invariant");
}
}
#endif
return;
}
if (mark == markWord::from_pointer(lock)) {
// If the object is stack-locked by the current thread, try to
// swing the displaced header from the BasicLock back to the mark.
assert(dhw.is_neutral(), "invariant");
if (object->cas_set_mark(dhw, mark) == mark) {
return;
}
}
// We have to take the slow-path of possible inflation and then exit.
// The ObjectMonitor* can't be async deflated until ownership is
// dropped inside exit() and the ObjectMonitor* must be !is_busy().
ObjectMonitor* monitor = inflate(THREAD, object, inflate_cause_vm_internal);
monitor->exit(true, THREAD);
}
ObjectSynchronizer::reenter—函数 文件方法:src/hotspot/share/runtime/synchronizer.cpp
void ObjectSynchronizer::reenter(Handle obj, intx recursions, TRAPS) {
if (UseBiasedLocking) {
BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
// An async deflation can race after the inflate() call and before
// reenter() -> enter() can make the ObjectMonitor busy. reenter() ->
// enter() returns false if we have lost the race to async deflation
// and we simply try again.
while (true) {
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
if (monitor->reenter(recursions, THREAD)) {
return;
}
}
}
总结
通过查看同步代码块编译之后的可以看到,sychronized实现其实通过改变markword来标记对象的锁状态,具体markword对应的锁状态,请看下章节介绍。
一个在网络中翱翔的混子