JDK7中ReentrantLock源码解析(3)

来源:互联网 发布:mac六国循环重启 恢复 编辑:程序博客网 时间:2024/06/01 19:15

在阅读此篇文章前请确保对重入锁获取锁的源码有一定的了解,如果对重入锁获取锁源码不太清楚的可以参考:http://ericchunli.iteye.com/blog/2393222。ReentrantLock中对锁的释放比锁的获取容易很多,无论是对于公平锁还是非公平锁,它们的实现相同。对于锁的释放也是通过Sync实现的。

 

ReentrantLock锁的释放unlock()源码解析:

此处unlock()只是尝试释放锁,不一定能成功释放锁。当前线程必须获取当前锁才能释放,一旦释放锁后会将当前计数器count减少,如果count为0则表示释放锁成功。如果没有获得当前锁则会抛出IllegalMonitorStateException异常。

public void unlock() {

// 通过AQS的release()函数来实现解锁

sync.release(1); // 1表示锁的的状态参数,类似acquire(1)

}

 

release()源码解析:

public final boolean release(int arg) {

  if (tryRelease(arg)) {

   Node h = head;

   if (h != null && h.waitStatus != 0)

     unparkSuccessor(h);

    return true;

  }

  return false;

}

释放锁的源码比获简单,此处release会先调用tryRelease()来尝试释放当前线程锁持有的锁,解锁成功则唤醒后继等待线程并返回true,解锁不成功则直接返回false。

 

tryRelease()源码解析:

此处tryRelease是在ReentrantLock的Sync类中实现而不是AQS中实现。

protected final boolean tryRelease(int releases) {

int c = getState() - releases;

// 当前线程是否持有当前的独占锁

  if (Thread.currentThread() != getExclusiveOwnerThread())

    throw new IllegalMonitorStateException();

  boolean free = false;

  if (c == 0) {

    free = true;

    setExclusiveOwnerThread(null); // 锁被释放,可以被获取

  }

  // 设置当前线程的锁的状态,释放之后应该是0。

  setState(c);

  return free;

}

 

实现总结:ReentrantLock锁的释放比较简单,通过设置exclusiveOwnerThread为null和重置state值来实现锁的释放,此处需要保证exclusiveOwnerThread是当前线程且state的值为0,因为存在重入的情况。如果head节点不为null并且waitStatus不为0的情况下,需要唤醒后继节点。