public class CLHLock implements Lock {
????// 当前节点本地变量
? ?private static ThreadLocalcur curNodeLocal =new ThreadLocal<>();
// Clh 队列的尾部指针 使用 AtomicReference,方便进行CAS操作
?private AtomicReference tail = new AtomicReference<>();
public CLHLock() {
????// 设置尾部节点
? ? tail.getAndSet(Node.EMPTY);
}
//加锁操作将节点添加到等待队列的尾部
@Override
public void lock() {
????Node curNode = new Node(true, null);
? ? Node preNode =tail.get();
? ? // cas自旋 将当前节点插入到队列尾部
? ? while (!tail.compareAndSet(preNode, curNode)) {
????????preNode =tail.get();
? ? }
? ? ? ?//设置前驱
? ? curNode.setPreviewNode(preNode);
? ? //自旋监听前驱节点locked变量直到其中的值变为false
? ? // 若前继节点为true 则表示一直抢占锁
? ? while (curNode.getPreviewNode().locked) {
? ? ?// 让出cpu 提高性能
? ? ? ? Thread.yield();
? ? }
? ? //能执行到这里 获取到锁了
? ? System.out.println("获取到锁了!!!!");
? ? //将当前节点缓存到本地变量中 释放锁会用到
? ? curNodeLocal.set(curNode);
}
?// 释放锁
?@Override
public void unlock() {
Node curNode =curNodeLocal.get();
? ? curNode.setLocked(false);
? ? curNode.setPreviewNode(null); //help full gc
? ? curNodeLocal.set(null);
}
@Data
static class Node {
? ?//true:当前线程正在抢占锁、或者已经占有锁
? ? // false:当前线程已经释放锁,下一个线程可以占有锁了
? ? volatile boolean locked;
? ? //前一个节点,需要监听其 locked 字段
? ? Node previewNode;
? ? public Node(boolean locked, Node previewNode) {
? ? ? ? this.locked = locked;
? ? ? ? this.previewNode = previewNode;
? ? }
? ? ?//空节点
? ? public static final NodeEMPTY = new Node(false, null);
}
public static int sum =0;
@Test
public void testCLHLockCapability() {
? ?//每条线程执行轮数
? ? final int turns =10000;
? ? //线程数
? ? final int threads =10;
? ? //线程池模拟测试
? ? ExecutorService executorService = Executors.newFixedThreadPool(threads);
? ? CLHLock lock = new CLHLock();
? ? long start = System.currentTimeMillis();
? ? CountDownLatch countDownLatch = new ? CountDownLatch(threads);
? ? for (int i =0; i < threads; i++) {
????????executorService.submit(() ->{
? ? ? ? ? ? ? ?for (int j =0; j < turns; j++ ) {
? ? ? ? ? ? ? ? ? ? lock.lock();
? ? ? ? ? ? ? ? try {
????????????????????sum++;
? ? ? ? ? ? ? ? }? finally {
????????????????????lock.unlock();
? ? ? ? ? ? ? ? }
????????}
????????????countDownLatch.countDown();
? ? ? ? });
? ? }
try {
????????//等待倒数闩归 0,所有线程结束
? ? ? ? countDownLatch.await();
? ? } catch (InterruptedException e) {
????????e.printStackTrace();
? ? }
????float time = (System.currentTimeMillis() - start) /1000F;
? ? System.out.println("运行的时长为:" + time);
? ? System.out.println("累加结果为:" +sum);
????}
}