java并发-AQS-ReentrantLock

465 阅读4分钟

AQS

AbstractQueuedSynchronizer

关注点

Node
先进先出的队列
volatile int state
标记当前锁是否被获取或者获取的次数(可重入锁)
tryAcquire()
排它锁使用的尝试获取锁方法,需要子类重写
tryRelease()
排它锁使用的尝试释放锁方法,需要子类重写
tryAcquireShared()
共享锁使用的尝试获取锁方法,需要子类重写
tryReleaseShared()
共享锁使用的尝试释放锁方法,需要子类重写

ReentrantLock

有一个成员变量 Sync sync (同步器)
Sync 实现了AQS接口
1.实现了Lock接口
2.使用了AQS同步器

实例代码

	private Lock lock = new ReentrantLock();

	public void method() {

		lock.lock();

		try {

			Thread.sleep(1000);
			System.out.println("hello");

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}

	}

ReentrantLock 构造方法

public ReentrantLock() {
    sync = new NonfairSync();
}

public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

/*
由上面两个构造方法可以看到
可能根据我们选择的构造方法或者是传递的参数创建不同的 同步器
NonfairSync 为 非公平的
FairSync 为 公平的 
默认不传递参数为 非公平的锁
*/

lock()

//可以看出,是根据不同的同步器调用不同的同步器的lock方法
public void lock() {
    sync.lock();
}
FairSync.lock()
final void lock() {
	//这个方法是父类AQS的方法
    acquire(1);
}

public final void acquire(int arg) {
	//上面有提过 tryAcquire 方法,尝试获取锁,需要子类实现
    //当前类为FairSync 所以调用的 FairSync.tryAcquire 方法
    //假如tryacquire方法返回true表示为获取锁成功,&& 后面的表达式不会执行
    //假如tryAcqyire方法返回false表示获取锁失败,进入等待队列并执行selfInterrupt 中断当前线程
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

// java.util.concurrent.locks.ReentrantLock.FairSync.tryAcquire(int) 参数值为1
protected final boolean tryAcquire(int acquires) {
		//获取当前线程
        final Thread current = Thread.currentThread();
        //获取AQS.state的值,state 就是用来判断是否存在线程获取到锁
        int c = getState();
        //假如为0 表示 现在没有线程获取到锁
        if (c == 0) {
        	//hasQueuedPredecessors 方法 判断等待队列中是否存在 等待的线程 (因为是公平锁)
            //compareAndSetState CAS 操作设置 state 的值
            //setExclusiveOwnerThread 设置当前获取锁的线程为 当前线程
           	//所以  这个 if 中的表达式的意思 是: 
            //等待队列中没有线程在等待 并 CAS 操作成功 并且设置线程成功 则返回 true  表示获取锁成功
            if (!hasQueuedPredecessors() &&
                compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
            }
        }
        // 假如 state 的值不为 0 表示存在线程争取这个锁
        //判断争取到锁的线程是否当前线程 (可重入锁)
        else if (current == getExclusiveOwnerThread()) {
        	// 假如是 累加 state的值,表示重入次数
            int nextc = c + acquires;
            if (nextc < 0)
                throw new Error("Maximum lock count exceeded");
            setState(nextc);
            return true;
        }
        return false;
    }


NonfairSync.lock()
final void lock() {
		//直接就去尝试获取锁(设置state的值)这就是和公平锁的区别
      if (compareAndSetState(0, 1))
      		//假如获取到了,设置独占线程为 当前线程
          setExclusiveOwnerThread(Thread.currentThread());
      else
      		//假如不成功 , 调用AQS的 acquire 方法,这个方法上面提及了直接看 tryAcquire
          acquire(1);
  }
  
protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}


//这个方法和 公平的同步器 基本雷同,唯一的区别的少了一行代码
//hasQueuedPredecessors
//也就是说,非公平的不需要判断等待队列里面是否存在等待线程 , 直接就去抢占锁
//由此可见 从代码逻辑看  非公平锁 有两次直接抢占锁的地方 , 一次在 lock方法中  一次当前方法
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;
}
  
  

unlock()

不管是公平锁还是非公平锁都是用的一个方法
public void unlock() {
    sync.release(1);
}

//这是AQS的release方法
public final boolean release(int arg) {
	//需要子类实现的tryRelease方法,表示是否释放锁公共
      if (tryRelease(arg)) {
          Node h = head;
          if (h != null && h.waitStatus != 0)
          		//假如释放锁成功 并且等待队列中有值
                //去唤醒一个线程
              unparkSuccessor(h);
          return true;
      }
      return false;
  }
  
  
protected final boolean tryRelease(int releases) {
		// 对 state 的值 -1
      int c = getState() - releases;
      //假如释放锁的线程和持有锁的线程不同 报错
      if (Thread.currentThread() != getExclusiveOwnerThread())
          throw new IllegalMonitorStateException();
      boolean free = false;
      // 假如 state 值为0 表示释放锁成功
      if (c == 0) {
          free = true;
          // 设置 独占线程 为 null
          setExclusiveOwnerThread(null);
      }
      setState(c);
      return free;
  }