AbstractQueuedSynchronizer

java并发编程之美 学习笔记

AbstractQueuedSynchronizer

AbstractQueuedSynchronizer简称AQS,它是实现同步器的基础组件(如:ReentrantLock,Semaphore,CountDownLatch)。
AQS

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
	/*
 	 *      +------+  prev +-----+       +-----+
     * head |      | <---- |     | <---- |     |  tail
     *      +------+       +-----+       +-----+
     *  
     **/
	 private transient volatile Node head;
	 private transient volatile Node tail;

	 private volatile int state;
}
  • AQS是一个FIFO的双向队列,内部通过headtail记录队首和队尾元素,元素类型为Node.
  • state(后续会详细讲解):
    • 对于ReentrantLock: 表示当前线程获取锁的可重入次数;
    • 对于ReentrantReadWriteLock:
      • 高16为,表示获取该读锁的次数
      • 低16位,表示获取写锁线程可重入次数;
    • 对于Semaphore: 表示可用信号的个数
    • 对于CountDownLatch:表示计数器当前值;

Node
Node 中的 thread 变量用来存放进入 AQS队列里面的线程.

 static final class Node {
        //共享模式,
        static final Node SHARED = new Node();

        //独占模式
        static final Node EXCLUSIVE = null;

        static final int CANCELLED =  1;
        static final int SIGNAL    = -1;
        static final int CONDITION = -2;
        static final int PROPAGATE = -3;
        /**
         * CANCELLED == 1 , thread被取消;
		 * SIGNAL == -1   , thread需要被唤醒
		 * CONDITION == -2, thread在condition队列中;
		 * PROPAGATE == -3, 释放共享资源时,需要通知其他节点
		 * 				0,	 表示当前节点在sync队列中,等待着获取锁。		
         */
        volatile int waitStatus;

 
        volatile Node prev;
        volatile Node next;

        volatile Thread thread;

        //存储condition队列中的后继节点。
        Node nextWaiter;

     
        final boolean isShared() {
            return nextWaiter == SHARED;
        }

    }

ConditionObject
AQS有个内部类 ConditionObject,用来结合锁实现线程同步 。
ConditionObject是条件变量,每个条件变量对应一个条件队列(单向链表队列),其用来存放调用条件变量的await()方法后被阻塞的线程.

对于AQS来说,线程同步的关键是对状态state进行操作。根据state是否属于一个线程,操作state的方式分为独占和共享两种方式;

//独占锁获取&释放
public final void acquire(int arg) {}
public final void acquireInterruptibly(int arg){}
public final boolean tryAcquireNanos(int arg, long nanosTimeout){}
public final boolean release(int arg) {}

//共享锁获取&释放
public final void acquireShared(int arg) {}
public final void acquireSharedInterruptibly(int arg){}
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout){}	
public final boolean releaseShared(int arg) {}

独占锁

获取锁
获取锁,在writeLock.lock()内部逻辑中调用;

	/*
 	 *      +------+  prev +-----+       +-----+
     * head |      | <---- |     | <---- |     |  tail
     *      +------+       +-----+       +-----+
     *  
     **/
    private transient volatile Node head;
    private transient volatile Node tail;
    private volatile int state;

    //获取锁,在writeLock.lock()内部逻辑中调用;
    public final void acquire(int arg) {
    	//1.首先尝试获取资源,当获取失败时进行2, 若获取成功则直接跳出
    	//1.由子类实现,模板方法
        if (!tryAcquire(arg) && // 1
            acquireQueued(
            			addWaiter(Node.EXCLUSIVE)	// 2 ,此时的mode为独占模式
            			, arg) //3 调用LockSupport.park(this); 挂起当前线程;
            )

        	//中断当前线程..
            selfInterrupt();
    }


 	//2.
    private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        Node pred = tail;
        if (pred != null) {
        	//当pred不为空时,同enq中 else{}部分代码,
        	//将node.prev指向tail(这里是pred),然后将自身设置为tail
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }

        //2.1 当tail为null,或者compareAndSetTail(pred,node)失败时,调用enq入列;
        enq(node);
        return node;

    }

    //2.1
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { 
        		// 初始化,设置一个“哨兵” Heder
                if (compareAndSetHead(new Node()))
                    tail = head; //初始化成功时,tail也指向“哨兵”
            } else {
            	//将node.prev指向tail, 然后将自身设置为tail
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

释放锁
释放锁,如在 writeLock.unlock()中调用;

public final boolean release(int arg) {
  	//1.如果tryRelease成功进行释放锁操作
  	//由子类实现...
      if (tryRelease(arg)) {
          Node h = head;
          if (h != null && h.waitStatus != 0)
          	//2.
              unparkSuccessor(h);
          return true;
      }
      return false;
  }


  //2.从后续的thread中,找出一个然后执行LockSupport.unpark();
  private void unparkSuccessor(Node node) {
      int ws = node.waitStatus;
      if (ws < 0)
      	//将当前node
          compareAndSetWaitStatus(node, ws, 0);

      Node s = node.next;
      if (s == null || s.waitStatus > 0) {
          s = null;
          for (Node t = tail; t != null && t != node; t = t.prev)
              if (t.waitStatus <= 0)
                  s = t;
      }
      if (s != null)
          LockSupport.unpark(s.thread);
  }

例:代码跟踪

public class MultiLockTest {
	private ReentrantLock lock = new ReentrantLock();

	public  void write(String msg){
		lock.lock();

		System.out.println(LocalDateTime.now()+"    ["+Thread.currentThread().getName()+"]  write() : "+msg);
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		lock.unlock();
	}

	public static void main(String[] args) throws InterruptedException {
		MultiLockTest app = new MultiLockTest();

		Thread thread1 = new Thread(() -> {
			app.write("111");
		},"thread1");
		Thread thread2 = new Thread(() -> {
			app.write("222");
		},"thread2");

		thread1.start();
		Thread.sleep(10);
		thread2.start();
	}
}

在这里插入图片描述

共享锁(略)

后续讲读写锁时再详细分析.

条件变量的支持

public class LockConditionTest {
	ReentrantLock lock = new ReentrantLock();
	Condition notEmptyCondition = lock.newCondition();

	Queue queue = new ArrayDeque(10);

	public void consume() {
		lock.lock();
		while (queue.isEmpty()) {
			try {
				System.out.println("consume队列为空,阻塞....");
				//queue为空,阻塞等待
				notEmptyCondition.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		System.out.println("消费了:" + queue.poll());

		lock.unlock();
	}

	public void product(Object obj) {
		lock.lock();
		queue.add(obj);

		System.out.println("生产了:" + obj);

		notEmptyCondition.signal();
		lock.unlock();
	}
}

上述代码作用等同于:

	public synchronized void consume2() {
		while (queue.isEmpty()) {
			wait();
		}
		
		//cosume sth
	}

	public synchronized void product2(Object obj) {
		//product sth
		notify();
	}
  • lock.lock()相当于进入了synchronized{ }代码块
  • lock.unlock()相当有退出了synchronized块
  • lock.newCondition() 创建了一个AbstractQueuedSynchronizer.ConditionObject对象
  • condition.await()相当于调用了object.wait()
  • condition.signal()相当于调用了object.notify();
  • condition.signalAll()相当于调用了object.notifyall();

ConditionObject

public class ConditionObject implements Condition, java.io.Serializable {
 	//condition自身持有的单向列表
     private transient Node firstWaiter;
     private transient Node lastWaiter;
}

await()

public final void await() throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            //1.添加thread到condition等待列表;
            Node node = addConditionWaiter();

            //2.释放当前线程获取的锁---更新state状态为0,此时锁可由其他线程获取
            int savedState = fullyRelease(node);
            int interruptMode = 0;

            //3. 当node.waitStatus == Node.CONDITION 时,返回false;
            while (!isOnSyncQueue(node)) {
            	//调用park方法挂起当前线程 ----- 
            	//直到当前线程被别的线程signale唤醒 ---- 执行后续的逻辑
                LockSupport.park(this);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
        	 
        	 // 重新尝试获取锁,执行后续的逻辑
        	 if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null) // clean up if cancelled
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
        }

        //1.
        private Node addConditionWaiter() {
            Node t = lastWaiter;

            //如果lastWaiter状态为CANCELLED ,从队列中清除;
            if (t != null && t.waitStatus != Node.CONDITION) {
                unlinkCancelledWaiters();
                t = lastWaiter;
            }

            //将当前线程 加入condition的等待队列中....
            Node node = new Node(Thread.currentThread(), Node.CONDITION);
            if (t == null)
                firstWaiter = node;
            else
                t.nextWaiter = node;

            //更新当前condition等待列表的lastWaiter为当前node;
            lastWaiter = node;
            return node;
        }

       	//2.
        final int fullyRelease(Node node) {
	        boolean failed = true;
	        try {
	            int savedState = getState();
	            //释放锁 --- 更新state状态..
	            if (release(savedState)) {
	                failed = false;
	                return savedState;
	            } else {
	                throw new IllegalMonitorStateException();
	            }
	        } finally {
	            if (failed)
	                node.waitStatus = Node.CANCELLED;
	        }
	    }

signal()

 public final void signal() {
        	//isHeldExclusively() 由子类实现..
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            if (first != null)
            	//1.激活condition等待队列的firstwatier激活
                doSignal(first);
        }

        private void doSignal(Node first) {
            do {
                if ( (firstWaiter = first.nextWaiter) == null)
                    lastWaiter = null;
                first.nextWaiter = null;
            } while (!transferForSignal(first) && //2.
                     (first = firstWaiter) != null);
        }

//2 调用了AbstractQueuedSynchronizer.transferForSignal()方法

//2. 
   final boolean transferForSignal(Node node) {
     	//将node的waitstaus更新为 0
       if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
           return false;

      //将condition队列中的节点 传输到aqs的等待队列中 ---在未来的时刻等待时机获取锁.
       Node p = enq(node);
       int ws = p.waitStatus;
       if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
       	//调用LockSupport.unpark 激活thread
           LockSupport.unpark(node.thread);
       return true;
   }

代码跟踪

public void testTrace(){
	Thread thread1 =	new Thread(() -> {
		tool.consume();
	},"consumer_thread");
	thread1.start();
	Thread.sleep(10);
	tool.product("xx");
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值