jdk 源码分析(12)java condition 条件锁

在分析ReentrantReadWriteLock 时知道多个线程在争论一个state,那么当时数据放在那里呢。都是放在syns里,这个类继承了AbstractQueuedSynchronizer,而里面的node(链表)就是存储数据的。 所以其实所有的lock 是离不开的队列的。今天的condition 也是离不开队列,也离不开lock,所以其实现类就放在 AbstractQueuedSynchronizer。名为:ConditionObject
Condition 通过 lock的newCondition() 方法生存,就像wait和notify 离不开同步块或者同步方法一样。
Condition newCondition();

每一个condition存储了头和尾
private transient Node firstWaiter;
/** Last node of condition queue. */
private transient Node lastWaiter;
await操作:
添加一个await操作,就是放里面添加一个节点:(如果看不懂,可以先看看数据结构,学习java 也是必须懂数据结构和算法的,如果不懂底层,能力很难提高,发个感慨------最近面试了很多人,其中很多人都工作很多年,但是一问三不知,工作都停留表面,可能是工作内容的原因(比如:工作轻松,或者完成一个demo,或者完成一些简单后台工作),同样的项目,努力的人会去努力了解底层,了解全部架构,知其然,该知其所以然,才能提高哦,可是什么都不开,天天就是MVC,写写restful,完成个页面,完成个后台,拿到的都是别人搭好的架构和接口要求,这样你做再久也就这样了。。。。。。话多余了。。。。。)
 
  
  1. private Node addConditionWaiter() {
  2. Node t = lastWaiter;
  3. // If lastWaiter is cancelled, clean out.
  4. if (t != null && t.waitStatus != Node.CONDITION) {
  5. unlinkCancelledWaiters();
  6. t = lastWaiter;
  7. }
  8.             //注意这个,将节点变成了条件等待。
  9. Node node = new Node(Thread.currentThread(), Node.CONDITION);
  10. if (t == null)
  11. firstWaiter = node;
  12. else
  13. t.nextWaiter = node;
  14. lastWaiter = node;
  15. return node;
  16. }

signal操作:
重头开始遍历,依次做 transferForSignal
 
   
  1. private void doSignal(Node first) {
  2. do {
  3. if ( (firstWaiter = first.nextWaiter) == null)
  4. lastWaiter = null;
  5. first.nextWaiter = null;
  6. } while (!transferForSignal(first) &&
  7. (first = firstWaiter) != null);
  8. }

会去改变   waitStatus 的值,看来condition也是争一个变量了
 
   
  1. final boolean transferForSignal(Node node) {
  2. /*
  3. * If cannot change waitStatus, the node has been cancelled.
  4. */
  5. if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
  6. return false;
  7. Node p = enq(node);
  8. int ws = p.waitStatus;
  9. if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
  10. LockSupport.unpark(node.thread);
  11. return true;
  12. }

对象的等待和running:

这里涉及到变量的变化,还有一个就是怎么停车的。是通过 LockSupport,可以参考我的(  jdk 源码分析(10)java unsafe 分析) 
等待:

 
   
  1. public final void await() throws InterruptedException {
  2. if (Thread.interrupted())
  3. throw new InterruptedException();
  4.             //添加节点,并且节点是waitStatus 是condition(-2)
  5. Node node = addConditionWaiter();
  6. int savedState = fullyRelease(node);
  7. int interruptMode = 0;
  8. while (!isOnSyncQueue(node)) {
  9.                    //停车
  10. LockSupport.park(this);
  11. if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
  12. break;
  13. }
  14. if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
  15. interruptMode = REINTERRUPT;
  16. if (node.nextWaiter != null) // clean up if cancelled
  17. unlinkCancelledWaiters();
  18. if (interruptMode != 0)
  19. reportInterruptAfterWait(interruptMode);
  20. }

 释放等待:
  1. final boolean transferForSignal(Node node){
  2. /*
  3. *If cannot change waitStatus, the node has been cancelled.
  4. */
  5. if(!compareAndSetWaitStatus(node,Node.CONDITION,0))
  6. return false;
  7. Node p = enq(node);
  8. int ws= p.waitStatus;
  9.         //数据被signal 。unpark
  10. if(ws>0||!compareAndSetWaitStatus(p, ws,Node.SIGNAL))
  11. LockSupport.unpark(node.thread);
  12. return true;
  13. }


到此结束:
condition 用一个链表(Node)队列(FIFO)缓存wait,通过争论waitstute来改变状态,通过park和unpark来释放和等待

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值