CLH 锁

概述

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

上一篇:什么是网络爬虫,网络爬虫有什么用?


下一篇:MySQL 默认隔离级别是RR,为什么阿里这种大厂会改成RC?