概述
CLH锁是一种自旋锁,能确保无饥饿性,提供先来先服务的公平性。所谓的自旋是指:当线程试图去拿已经被其它线程占有的锁时,当前线程不会进入阻塞态,而是进入一个死循环去自旋的获取锁,获取到锁之后退出死循环。
同时CLH锁也是一种基于链表的可扩展,高性能,公平的自旋锁,申请线程只在本地变量上自旋轮询前驱的状态,如果发现前驱释放了锁就结束自旋。
实验
public class CLHLock implements Lock {
private final AtomicReference<QNode> tail;
private final ThreadLocal<QNode> myPred;
private final ThreadLocal<QNode> myNode;
public CLHLock() {
tail = new AtomicReference<QNode>(new QNode());
myNode = new ThreadLocal<QNode>() {
protected QNode initialValue() {
return new QNode();
}
};
myPred = new ThreadLocal<QNode>();
}
private static class QNode {
volatile boolean locked;
}
@Override
public void lock() {
QNode node = (QNode) myNode.get();
node.locked = true;
QNode pred = (QNode) tail.getAndSet(node);
myPred.set(pred);
while (pred.locked) {
}
}
@Override
public void unlock() {
QNode node = (QNode) myNode.get();
node.locked = false;
myNode.set(null);
myPred.set(null);
}
@Override
public void lockInterruptibly() throws InterruptedException {
// TODO Auto-generated method stub
}
@Override
public boolean tryLock() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
// TODO Auto-generated method stub
return false;
}
@Override
public Condition newCondition() {
// TODO Auto-generated method stub
return null;
}
}
public class CLHLockTest {
public static int tmp = 0;
public static CLHLock lock = new CLHLock();
public static void main(String[] args) {
for (int i = 0; i < 50; i++) {
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
}
System.out.println(CLHLockTest.tmp);
}
}
class Run implements Runnable {
@Override
public void run() {
CLHLockTest.lock.lock();
CLHLockTest.tmp++;
CLHLockTest.lock.unlock();
}
}
CLHLock使用tail 这个变量来标记队尾,当每个线程执行lock操作的时候,会生成相对应的myPred(指向前一个线程,以便监听前一个线程的执行情况,如果前一个线程myNode.locked = true, 这个线程会一直执行死循环来自旋;如果前一个线程myNode.locked = false; 这个线程就可以获取到锁了),myNode(用来给它的后继节点作为监听对象)的线程局部变量。当一个线程获取到锁后进行解锁时:它会获取自身的myNode,将其中的locked 标志位置为 false, 这样它的后继节点就可以从死循环中跳出来了(拿到锁了)。
如有错误希望大家能指出来
参考资料:
http://www.cnblogs.com/yuyutianxia/p/4296220.html
http://googi.iteye.com/blog/1736570