ReentrantLock之Lock方法

ReentranLock  JDK 1.8 类源码如下:

public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;
    /** Synchronizer providing all implementation mechanics */
    private final Sync sync;
    ...
    abstract static class Sync extends AbstractQueuedSynchronizer {
      ...
      ...
      /**
       * Performs {@link Lock#lock}. The main reason for subclassing
       * is to allow fast path for nonfair version.
       */
      abstract void lock();

      /**
      * Performs non-fair tryLock.  tryAcquire is implemented in
      * subclasses, but both need nonfair try for trylock method.
      */
      final boolean nonfairTryAcquire(int acquires) {
         final Thread current = Thread.currentThread();
         int c = getState();
         if (c == 0) {
             if (compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
             }
         }
         else if (current == getExclusiveOwnerThread()) {
             int nextc = c + acquires;
             if (nextc < 0) // overflow
               throw new Error("Maximum lock count exceeded");
             setState(nextc);
             return true;
         }   
        return false;
      }
     ...
   }
   ...
   /**
 * Sync object for non-fair locks
 */
static final class NonfairSync extends Sync {
    private static final long serialVersionUID = 7316153563782823691L;

    /**
     * Performs lock.  Try immediate barge, backing up to normal
     * acquire on failure.
     */
    final void lock() {
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }

    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
}

/**
 * Sync object for fair locks
 */
static final class FairSync extends Sync {
    private static final long serialVersionUID = -3000897897090466540L;

    final void lock() {
        acquire(1);
    }

    /**
     * Fair version of tryAcquire.  Don't grant access unless
     * recursive call or no waiters or is first.
     */
    protected final boolean tryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
            if (!hasQueuedPredecessors() &&
                compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
            }
        }
        else if (current == getExclusiveOwnerThread()) {
            int nextc = c + acquires;
            if (nextc < 0)
                throw new Error("Maximum lock count exceeded");
            setState(nextc);
            return true;
        }
        return false;
    }
}
 ...
}

公平锁和非公平锁都调用了acquire(1);方法,此方法如下:

tryAcquire方法如下:如果state状态为0,则获取锁成功,否则(红色框里是重入获取锁的实现,可见是)判断当前线程是否为已获得锁的线程,如果是,则state加1,否则获取失败。

补充:getState是Sync 的父类AbstractQueuedSynchronizer的方法,读者可阅读此源码进一步研究。

state定义如下:

compareAndSetState(0, 1): CAS 原子性设置(由硬件保证,cpu执行汇编)setExclusiveOwnerThread(Thread.currentThread()) : 设置exclusiveOwnerThread变量/**
 * The current owner of exclusive mode synchronization.
 */
private transient Thread exclusiveOwnerThread;
标记当前获取锁的线程信息。
acquire中调用了addWaiter,此方法如下:

可见是将当前线程加入阻塞队列中

所以acquire方法总体执行的是,判断锁的state是否为0,如果是则加锁成功state为1,将当前获取锁的线程标记,否则判断当前获取锁的线程是否为已拿到锁的线程,如果是,state+1 获取锁成功(可重入性);否则,失败,将自己放入队列中(尾插法),执行selfInterrupt();优雅中断(阻塞)。

/**
 * Convenience method to interrupt current thread.
 */
static void selfInterrupt() {
    Thread.currentThread().interrupt();
}

再来看看公平锁和非公平锁的不同:

从源码看,两者在lock中不同在于acquire方法tryAcquire的实现

看源码可知公平锁的实现中多了红框的内容:

此端代码是判断当前线程是否为列队头中的线程。。。在阻塞的线程中只有头线程才能获取成功锁

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值