java多线程编程-ReentrantLock笔记

来源:互联网 发布:苹果rar解压软件 编辑:程序博客网 时间:2024/04/29 04:13


基础知识:原子操作函数CAS

compareAndSet(int expect, int update)
setState(int value)
getState()
详细定义参见链接:http://www.blogjava.net/mstar/archive/2013/04/24/398351.html


基础知识:park和unpark:

        目前在Java语言层面能实现阻塞唤醒的方式一共有三种:suspend与resume组合、wait与notify组合、park与unpark组合。其中suspend与resume因为存在无法解决的竟态问题而被Java废弃,同样,wait与notify也存在竟态条件,wait必须在notify之前执行,假如一个线程先执行notify再执行wait将可能导致一个线程永远阻塞,如此一来,必须要提出另外一种解决方案,就是park与unpark组合,它位于juc包下,应该也是因为当时编写juc时发现java现有方式无法解决问题而引入的新阻塞唤醒方式,由于park与unpark使用的是许可机制,许可最大为1,所以unpark与park操作不会累加,而且unpark可以在park之前执行,如unpark先执行,后面park将不阻塞。
        注意,unpark需要指定唤醒的线程,即一次只能唤醒一个线程。


Lock概述

       先尝试加锁,如果失败,则将其保存在队列尾部,并死循环:尝试加锁,失败则阻塞等待唤醒。


Lock之尝试加锁:nonfairTryAcquire

概述:定义了“持有数”的原子变量,通过CAS函数来操作。同时,还有个“占有线程”(ExclusiveOwnerThread)的变量,但为了提升性能或其他原因,该变量不使用CAS函数操作,因此操作时要注意时间窗口和死锁等问题。


伪代码如下:
持有数=getState
持有数==0-->compareAndSetState(0,增加值)==true-->setExclusiveOwnerThread(当前线程)
持有数!=0-->getExclusiveOwnerThread==当前线程 -->持有数+=增加值-->setState(持有数)


注意,当线程A执行完compareAndSetState(0,增加值)==true后,线程B执行getState获取值>0,随后B执行getExclusiveOwnerThread,和A执行setExclusiveOwnerThread的顺序是随机的, 如果A先,则B不会进入循环;如果B先,假如B此时获取到“占有线程”是自己进入循环,同时A也继续执行进入循环,理论上可能存在问题。但实际上,后一个情况不会发生。因为通过分析unlock代码,unlock中最后一部分,用CAS设置“持有数”前,如果检测到“持有数”==0,会将“占有线程”设置为null。则如果getExclusiveOwnerThread在setExclusiveOwnerThread之前执行,getExclusiveOwnerThread获取到的是null,不存在问题。 

Lock之队列操作阻塞

紧接“Lock概述”部分,继续细化:
  1. 为了保证相对公平性,等待的越久的线程应该更有可能拿到锁,因此采用先进先出队列,在死循环中是对队首节点进行尝试加锁操作。死循环每一轮 开始都会node=node.prenode(),保证了不会真的死循环。
  2. 由于允许对阻塞等待队列中的线程cancel操作,因此,有可能队列位置m前面的大部分线程都是cancel状态,就应该将其剔除重建队列。
  3. unlock中unpark时,是对队首的节点进行unpark唤醒。该线程唤醒后,在死循环中会进入队首节点的尝试加锁操作逻辑,有很大概率会真正获取锁,但可能被另一个刚好在调用lock的尝试加锁操作的线程X抢掉锁,如果发生了,则重新进入阻塞,待X进行unpark时又将其唤醒....
  4. 代码逻辑看上去像:park等待唤醒,被唤醒后,看是否是队首再获取锁,如果不是队首则park继续阻塞。相当于线程A释放锁并unpark,阻塞中的线程B被唤醒,然后发现不是队首因此重新park阻塞。至此,线程A释放了锁和唤醒信号,然后线程B浪费了信号,没有任何一个线程获取到锁.....实际上,这个情况是不会发生的!因为,线程A进行unpark时是指定的队首节点,所以B唤醒后一定会进入尝试获取锁流程,此时,确实有可能失败并重新进入阻塞,但此时是因为被另一个线程C抢占了锁(见前一小节)。即始终有线程获取到了锁,不会丢失。


参考资料:http://www.cnblogs.com/longshiyVip/p/5213812.html
0 0