synchronized关键字原理解析(一)

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对应的锁状态,请看下章节介绍。


一个在网络中翱翔的混子
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值