package cn.mn.app.ls;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;
/**
* 先进先出锁
* 公平锁,不可重入
* locked 记录锁状态,被占用为true,未被任何
* 线程占用为false,AtomicBoolean 确保线程安全性
* waiters 线程队列,先进入队列的线程优先获取锁,确保公平性
* exusiveOwnThread 占有锁的线程
* 获取锁: 自旋 检查条件如果对列的head是其他线程,或者当前线
* 程但是锁被其他线程占有了,则挂起,如果中断醒来,
* 撤销中断,记录中断状态等待获取到锁后补上中断。获取
* 到锁后结束自旋,设置当前线程为占有锁的线程,在线程
* 队列移除线程,如果被中断过则补上中断。
* 释放锁: 如果当前线程不是占有锁的线程抛出异常,如果是,设置
* 锁的状态为false,唤醒队列的head节点线程。
* @author WQ
*
*/
public class FIFOLock {
private AtomicBoolean locked=new AtomicBoolean(false);
private Queue<Thread> waiters=new ConcurrentLinkedQueue<Thread>();
private transient Thread exusiveOwnThread;
public void lock(){
boolean wasInterrupted=false;
Thread current=Thread.currentThread();
waiters.add(current);
while(waiters.peek()!=current || !locked.compareAndSet(false, true)){
LockSupport.park(current);
if(Thread.interrupted())
wasInterrupted=true;
}
exusiveOwnThread=current;
waiters.remove();
if(wasInterrupted)
current.interrupt();
}
public void unlock(){
if(exusiveOwnThread!=Thread.currentThread())
throw new IllegalMonitorStateException();
locked.set(false);;
LockSupport.unpark(waiters.peek());
}
}