我理解的CLH


学而时习之,不亦说乎!

                             --《论语》

原创,转载请附原文链接,谢谢。

CLH

思路

  • 保持时序的锁基本思路就是将等待获取锁的线程放入集合,锁释放后,等待线程之一获取到锁。

问题

  • 如何排队?

    • CLH使用反向链表的形式进行排队。也就是后继节点主动询问,而不是前继节点主动通知。
  • 排队是否公平?

    • CLH是公平锁。即后申请获取锁的排在队列末尾。
  • 如何唤醒?

    • CLH通过每个线程自旋。每个等待线程通过不断自旋前继节点状态判断是否能获取到锁。

实现

  • CLH排队使用公平方式,锁内部需要保存【尾节点】的引用,每次排队线程加入到队列最末尾。
  • CLH锁使用反向链表方式进行排队,那么每个线程就需要维护【自己的状态】和保持一个【前向节点的引用】。
  • CLH使用一个【boolean值】表示当前线程获取锁状态。false表示当前线程释放锁;true表示当前线程等待获取锁或已经获取到锁。

代码

Lock.java

 
 
 
xxxxxxxxxx
 
 
 
 
package com.zby.clh;
public interface Lock {
    void lock();
    void unlock();
}
 

CLHLock.java

 
 
 
xxxxxxxxxx
 
 
 
 
package com.zby.clh;
import java.util.concurrent.atomic.AtomicReference;
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>() {
            @Override
            protected QNode initialValue() {
                return new QNode();
            }
        };
        myPred = new ThreadLocal<QNode>() {
            @Override
            protected QNode initialValue() {
                return null;
            }
        };
    }
    @Override
    public void lock() {
        QNode qnode = myNode.get();
        qnode.locked = true;
        QNode pred = tail.getAndSet(qnode);
        myPred.set(pred);
        while (pred.locked) {
        }
    }
    @Override
    public void unlock() {
        QNode qnode = myNode.get();
        qnode.locked = false;
        // myNode.set(myPred.get());这一行是否有必要???
    }
    private static class QNode {
        public volatile boolean locked;
    }
}
 

测试

 
 
 
xxxxxxxxxx
 
 
 
 
package com.zby.clh;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class CLHMain {
    private Lock lock = new CLHLock();
    public void say(String msg) {
        System.out.println(Thread.currentThread().getName() + " : 尝试获取锁");
        lock.lock();
        System.out.println(Thread.currentThread().getName() + " : 获取到锁");
        try {
            System.out.println(Thread.currentThread().getName() + msg + "?");
            TimeUnit.SECONDS.sleep(1);
            System.out.println(Thread.currentThread().getName() + msg + "!");
            TimeUnit.SECONDS.sleep(1);
            System.out.println(Thread.currentThread().getName() + msg + ".");
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            System.out.println(Thread.currentThread().getName() + " : 释放锁");
        }
    }
    public static void main(String[] args) throws Exception {
        String msg = "Hello,World";
        CLHMain clhMain = new CLHMain();
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    clhMain.say(msg);
                }
            });
        }
        executorService.awaitTermination(20, TimeUnit.SECONDS);
    }
}
 

结果

 
 
 
xxxxxxxxxx
 
 
 
 
pool-1-thread-1 : 尝试获取锁
pool-1-thread-2 : 尝试获取锁
pool-1-thread-1 : 获取到锁
pool-1-thread-1Hello,World?
pool-1-thread-3 : 尝试获取锁
pool-1-thread-4 : 尝试获取锁
pool-1-thread-5 : 尝试获取锁
pool-1-thread-1Hello,World!
pool-1-thread-1Hello,World.
pool-1-thread-1 : 释放锁
pool-1-thread-2 : 获取到锁
pool-1-thread-2Hello,World?
pool-1-thread-2Hello,World!
pool-1-thread-2Hello,World.
pool-1-thread-2 : 释放锁
pool-1-thread-3 : 获取到锁
pool-1-thread-3Hello,World?
pool-1-thread-3Hello,World!
pool-1-thread-3Hello,World.
pool-1-thread-3 : 释放锁
pool-1-thread-4 : 获取到锁
pool-1-thread-4Hello,World?
pool-1-thread-4Hello,World!
pool-1-thread-4Hello,World.
pool-1-thread-4 : 释放锁
pool-1-thread-5 : 获取到锁
pool-1-thread-5Hello,World?
pool-1-thread-5Hello,World!
pool-1-thread-5Hello,World.
pool-1-thread-5 : 释放锁
 

猜你喜欢

转载自www.cnblogs.com/zby9527/p/10815563.html
clh
今日推荐