java 多线程随笔(三)

本文介绍了跳表这种数据结构的设计思想及其在并发场景下的优势,对比了它与平衡树的区别,尤其强调了跳表在大数据量下的高性能表现。同时,文章还探讨了Java中的ConcurrentSkipListMap类及无锁并发机制的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java 多线程跳表和无锁

Skip List是 William Pugh 在1989年创建出来的(又见一个位神牛), 主要的目的就像他描述的那样,是用来替代平衡树的。跳表是一种随机性的数据结构,相对于平衡树来说,跳表更加的简单,能一口气实现红黑树,AVL这样的平衡树的人,还是太少了,而且内部确实复杂,调试, 用起来太麻烦。 同样跳表还可以做到平衡树那样的查找时间,特别是在并发的场景下面,由于红黑树的插入或者删除会做rebalance这样操作,那么影响的数据就会变多,锁的粒度就变大。但是跳表的插入或者删除操作影响的数据会很小,锁的粒度就会小,这样在大数据量的情况下,跳表的性能自然就会比红黑树要好。
如图
这里写图片描述
现在我们查询10可以很快查到出8-12中,提高查询效率。

简单介绍了跳表设计思想和应用,以及在高并发的情况下,优于平衡树的原因,所以跳表在并发计算领域出现了,redis, leveldb都用应用,并且在分布式里面可以利用跳表的无锁特性来实现优先级队列。跳表其实也是一种利用空间换取时间的方法。
下面说一下java 为我们实现的跳表,ConcurrentSkipListMap
在介绍这个类之前,介绍一下无锁,cas比较交换
之前我们多线程时需要加锁,但是加锁复杂和执行效率低。
这时我们可以这样考虑一个在多线程下,出错是小概率事件,这就是乐观,反之,就是悲观。
cas(v,e,n) v是要更新的变量 e预测值 N表示新值
v==e的是将n赋给v。在硬件层面,现在的处理器都支持原子化的CAS指令。在jdk5.0 以后,虚拟机使用这个指令实现并发操作和并发数据结构。
无锁的线程安全的整数 AtomicInteger,讲了这么多理论,举个栗子。

import java.util.concurrent.atomic.AtomicInteger;

public class IntTest {
    static AtomicInteger atomicInteger=new AtomicInteger();
    public static class AddThread implements Runnable{

        @Override
        public void run() {
            for(int k=0;k<10000;k++){
                atomicInteger.incrementAndGet();
            }
        }
    }
    public static void main(String args[]) throws InterruptedException {
        Thread []tt=new Thread[10];
        for(int i=0;i<10;i++){
            tt[i]=new Thread(new AddThread());
        }
        for(int i=0;i<10;i++){
            tt[i].start();
        }
        for(int i=0;i<10;i++){
            tt[i].join();
        }
        System.out.println(atomicInteger);
    }
}

输出为10000,所以实现了线程安全的Integer。
incrementAndGet在jdk 1.7下的源码

 public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
    }

可以看出就是在不断尝试中,乐观。
继续看源码发现,出现unsafe

public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

Unsafe 封装一些类型指针的操作,但是jdk的开发人员不希望我们进行调用。

public static Unsafe getUnsafe() {
        Class var0 = Reflection.getCallerClass(2);
        if(var0.getClassLoader() != null) {
            throw new SecurityException("Unsafe");
        } else {
            return theUnsafe;
        }
    }

我们直接调用返回,报错,抛出异常,原理双亲委派机制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值