网站建设资讯

NEWS

网站建设资讯

java的CLH队列锁是什么

本篇内容介绍了“java的CLH队列锁是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

我们提供的服务有:网站设计制作、成都网站制作、微信公众号开发、网站优化、网站认证、合肥ssl等。为上千家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的合肥网站制作公司

是什么

CLH队列锁是一种自旋锁,提供先来先服务的公平性。

有什么特点

CLH基于链表实现。线程只是在不断的自旋,不断地轮询前驱节点的状态,如果前驱节点释放了锁,那么线程结束自旋。
对于持锁时间很短的场景,比之间把线程阻塞住具有较高的性能,并能可以保持一定的公平性。
还有搭配自旋次数做深入的优化,使得使用场景更广,性能更好。

有什么作用

对于特定应用场景,使用这种锁可以提高性能,是一种锁的优化方向。

实现原理解析

核心理念就是,不要阻塞线程,用循环来替换。
一种LCH参考实现

public class ClhSpinLock implements Lock {

    /**
     * 前驱节点 每个线程
     */
    private final ThreadLocal prev = ThreadLocal.withInitial(Node::new);

    /**
     * 当前节点
     */
    private final ThreadLocal currentThreadNode = ThreadLocal.withInitial(Node::new);

    /**
     * 指向队列末尾节点
     * 

     * 值得注意 这个节点的默认值是false 也就是说 如果前驱节点是这个默认的节点 那么它是不会起到锁的作用      * 即 第一个线程进来 执行lock()操作之后 立即返回      * 

     * 还有所有就是 所有的线程都共享这个tail引用      * 链表推进是依靠这个共享的tail      */     private final AtomicReference tail = new AtomicReference<>(new Node());     public ClhSpinLock() {     }     /**      * 1.初始状态 tail指向一个node(head)节点      * +------+      * | head | <---- tail      * +------+      * 

     * 2.lock-thread加入等待队列: tail指向新的Node,同时Prev指向tail之前指向的节点      * +----------+      * | Thread-A |      * | := Node  | <---- tail      * | := Prev  | -----> +------+      * +----------+        | head |      * +------+      * 

     * +----------+            +----------+      * | Thread-B |            | Thread-A |      * tail ---->  | := Node  |     -->    | := Node  |      * | := Prev  | ----|      | := Prev  | ----->  +------+      * +----------+            +----------+         | head |      * +------+      * 3.寻找当前node的prev-node然后开始自旋      */     @Override     public void lock() {         // 值得注意的细节         // 如果是第一个线程进来         // 那么pred.locked是false 所以这个线程调用lock之后就直接返回了         // 第二个线程进来之后 它的pred就是第一个线程的         // 之后的线程以此类推         final Node currentThreadNode = this.currentThreadNode.get();         currentThreadNode.locked = true;         // 所有线程都通过这个tail的不断变换去推进         final Node prev = this.tail.getAndSet(currentThreadNode);         // 这个只是满足每个线程自己prev的设置 其实是可以省略掉的         this.prev.set(prev);         // 自旋         while (prev.locked) {         }     }     @Override     public void unlock() {         final Node node = this.currentThreadNode.get();         node.locked = false;         this.currentThreadNode.set(this.prev.get());     }     @Override     public void lockInterruptibly() throws InterruptedException {     }     @Override     public boolean tryLock() {         return false;     }     @Override     public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {         return false;     }     @Override     public Condition newCondition() {         return null;     }     private static class Node {         private volatile boolean locked;     } }

相关的测试代码

public class ClhSpinLockTest {

    private static int count = 0;

    private static void testLock(Lock lock) {
        try {
            lock.lock();

            System.out.println("任务启动线程名称:" + Thread.currentThread().getName() + " 任务开始时统计数:" + count + " 任务执行时间:" + System.currentTimeMillis());

            for (int i = 0; i < 100; i++) {
                count++;
            }

            System.out.println("任务启动线程名称:" + Thread.currentThread().getName() + " 任务结束时统计数:" + count);
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {

        int workerThreadNums = 5;

        // 这个锁是需要每个相关线程都需要持有的
        final ClhSpinLock clhSpinLock = new ClhSpinLock();
        // 这个是一个栅栏 目的是等到所有线程都执行完 看结果
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(workerThreadNums, () -> System.out.println("最终结果:" + count));

        for (int i = 0; i < workerThreadNums; i++) {
            new Thread(() -> {
                testLock(clhSpinLock);

                try {
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }).start();
        }
    }
}

优缺点

  1. 空间复杂度低

  2. 在不同CPU结构体系下,性能是不同的。

“java的CLH队列锁是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!


分享文章:java的CLH队列锁是什么
链接分享:http://cdweb.net/article/gogsjh.html