【Netty】FastThreadLocal比ThreadLocal快之源码解析

ThreadLocal

【并发设计模式】聊聊线程本地存储模式如何实现的线程安全
【Java并发】从simpleDateFormart聊聊threadlocal原理机制

前两篇中已经从源码角度进行剖析,本篇主要从设计角度剖析。

在并发中为了保证数据安全,可以采用数据隔离的方式 也就是大家都自己内部维护一份数据,在实际落地的时候,其实就是针对每个线程内部持有自己特殊的数据。ThreadLocal就是一个案例。

那么我们思考下,如果你是JDK的设计者你会如何设计,一般就是使用一个全局Map<Thread,具体数据>,显然是用这种方式,在写操作的时候,需要进行加锁,无论是lock 还是CAS的方式,都存在一定的性能损耗。

那么ThreadLocal是如何做的。因为数据是对于线程级别的,所以对于Thread来说,内部持有一个ThreadLocalMap,而这个就是一个Entry数组,Key是ThreadLocal,Value是具体数据。
在这里插入图片描述
在这里插入图片描述

优秀设计

线程内数据隔离,避免锁竞争

ThreadLocal巧妙使用内部持有一个私有的ThreadLocalMap来存储数据。可以避免锁竞争。

易用性,封装复杂性

在使用的时候,其实对于程序员来说,不需要了解具体的内部细节,直接操作ThreadLocal的set get就可以获取数据,使用起来比较好用,封装内部复杂性。

弱引用避免内存泄漏

其实主要就是两点 一个依赖于Key是软引用,当ThreadLocal外部不在使用的时候,就会进行下次GC的时候,回收,但是对应的value还存在,如何避免,那就是使用remove() , 当前 本身 get \ set 也会清除key=null 的数据。

使用线性探测法,而不是拉链法

	int i = key.threadLocalHashCode & (len-1);

在进行数据set的时候,使用的hash,那么有hash一定会存在hash冲突,ThreadLocalMap是如何解决的,答案是下探法。
在这里插入图片描述
一句话就是,如果当前位置有数据,那么就延续后一个位置,如果都满了,在进行扩容操作。

那么为什么ThreadLocalMap要这么设计,其实主要就是两点,第一个本身 时间效率存储的数据不多,并且ThreadLocalMap是一个数组,可以有效的利用内存数据的连续性 内存的预读性, 高效的查找和存储数据,第二点,空间效率,如果采用拉链法,那么就需要多存储一个next指针,占用一定的空间。

既然ThreadLocal已经这么优秀了,那么为什么还有Netty实现一个呢,答案其实就只要应对的场景不同,ThreadLocal本身只是提供一些少量数据的存储,对于支持高并发来说,极端情况下,线性探测法时间复杂度在O(N),以及在数据满之后,要进行的Rehash操作。当如还有内存泄漏的问题。

FastThreadLocal

最佳实践

具体使用其实就是通过创建FastThreadLocalThread 然后通过 FastThreadLocal 设置值。

        final FastThreadLocal fastThreadLocal = new FastThreadLocal();
        final FastThreadLocal fastThreadLocal2 = new FastThreadLocal();
        final FastThreadLocal fastThreadLocal3 = new FastThreadLocal();
        FastThreadLocalThread fastThreadLocalThread = new FastThreadLocalThread(()-> {
   
   
            fastThreadLocal.set("1");
            fastThreadLocal.get();

            fastThreadLocal2.set("2");
            fastThreadLocal2.get();

            fastThreadLocal3.set("3");
            fastThreadLocal3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qxlxi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值