当前位置:主页 > 软件编程 > JAVA代码 >

Java 基于AQS实现自定义同步器的示例

时间:2023-03-07 09:34:13 | 栏目:JAVA代码 | 点击:

一、AQS-条件变量的支持

在如下代码中,当另外一个线程调用条件变量的signal方法的时候(必须先调用锁的lock方法获取锁),在内部会把条件队列里面队头的一个线程节点从条件队列里面移除并且放入AQS的阻塞队列里面,然后激活这个线程。

public final void signal() {
 if(!isHeldExclusively()) {
  throw IllegalMonitorException();
 }
 Node first = firstWaiter;
 if(first != null){
  // 将条件队列头元素移动到AQS队列
  doSignal(first);
 }
}
private Node addConditionWaiter() {
 Node t = lastWaiter;
 ...
 // (1)
 Node node = new Node(Thread.currentThread(),Node.CONDITION);
 // (2)
 if(t == null){
  firstWaiter = node;
 }else {
  t.nextWaiter = node; // (3)
 }
 lastWaiter = node; // (4)
 return node;
}

二、基于AQS实现自定义同步器

package com.ruigege.LockSourceAnalysis6;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class NonReentrantLockME implements Lock,java.io.Serializable{
 // 内部帮助类
 private static class Sync extends AbstractQueueSynchronizer {
  // 是否锁已经被持有
  protected boolean isHeldExclusively() {
   return getState() == 1;
  }
  
  // 如果state为0,则尝试获取锁
  public boolean tryAcquire(int acquires) {
   assert acquires == 1;
   if(compareAndSetState(0,1)) {
    setExclusiveOwnerThread(Thread.currentThread());
    return true;
   }
   return false;
  }
  
  // 尝试释放锁,设置state为0
  protected boolean tryRelease(int release) {
   assert releases == 1;
   if(getState() == 0) {
    throw new IllegalMonitorStateException();
   }
   setExclusiveOwnerThread(null);
   setState(0);
   return true;
  }
  
  // 提供条件变量接口
  Condition newConditon() {
   return new ConditionObject();
  }
 }
 
 // 创建一个Sync来做具体的工作
 private final Sync sync = new Sync();
 
 public void lock() {
  sync.acquire(1);
 }
 
 public boolean tryLock() {
  return sync.tryAcquire(1);
 }
 
 public void unlock() {
  sync.release(1);
  
 }
 public Condition newCondition() {
  return sync.newConditon();
 }
 
 public boolean isLocked() {
  return sync.isHeldExclusively();
 }
 
 public void lockInterruptibly() throws InterruptedException {
  sync.acquireInterruptibly(1);
 }

 public boolean tryLock(long timeout,TimeUnit unit) throws InterruptedException {
  return sync.tryAcquireNanos(1,unit.toNanos(timeout));
 }
}

如上面的代码,NonReentrantLock定义了一个内部类Sync用来实现具体的锁的操作,Sync则继承了AQS ,由于我们实现的独占模式的锁,所以Sync重写了tryAcquire\tryRelease和isHeldExclusively3个方法,另外Sync提供了newCondition这个方法用来支持条件变量。

三、源码:

所在包:com.ruigege.ConcurrentListSouceCodeAnalysis5

https://github.com/ruigege66/ConcurrentJava

您可能感兴趣的文章:

相关文章