netty FastThreadLocal
所属分类 netty
浏览量 90
线程本地存储(Thread-Local Storage, TLS)
FastThreadLocal 使用数组而不是哈希表来存储数据,避免哈希冲突,提高访问速度。
每个FastThreadLocal实例在创建时会分配一个唯一的索引(index),
FastThreadLocal 必须和 FastThreadLocalThread 配套使用
FastThreadLocal利用了缓存行的特性,并使用缓存行填充解决了伪共享问题,进一步提高了性能
FastThreadLocal使用数组替代了Entry数组,Object[0]存储的是一个Set集合,从数组下标1开始都是直接存储的value数据。
FastThreadLocal 适合在多线程环境下,需要为每个线程维护独立数据副本的场景。
例如,在Netty的网络编程中,可以使用FastThreadLocal来存储每个连接的会话信息、用户认证信息等,从而避免线程间的数据干扰,提高程序的可维护性和安全性。
io.netty.util.concurrent.FastThreadLocal
A special variant of ThreadLocal that yields higher access performance when accessed from a FastThreadLocalThread.
Internally, a FastThreadLocal uses a constant index in an array, instead of using hash code and hash table, to look for a variable.
Although seemingly very subtle, it yields slight performance advantage over using a hash table, and it is useful when accessed frequently.
To take advantage of this thread-local variable, your thread must be a FastThreadLocalThread or its subtype.
By default, all threads created by DefaultThreadFactory are FastThreadLocalThread due to this reason.
Note that the fast path is only possible on threads that extend FastThreadLocalThread,
because it requires a special field to store the necessary state.
An access by any other kind of thread falls back to a regular ThreadLocal.
io.netty.util.concurrent.FastThreadLocalThread
public static InternalThreadLocalMap getIfSet() {
Thread thread = Thread.currentThread();
if (thread instanceof FastThreadLocalThread) {
return ((FastThreadLocalThread) thread).threadLocalMap();
}
return slowThreadLocalMap.get();
}
public class FastThreadLocalThread extends Thread {
private InternalThreadLocalMap threadLocalMap;
io.netty.util.internal.InternalThreadLocalMap
FastThreadLocal对ThreadLocal的优化
1. 数据结构优化
数组索引访问:FastThreadLocal使用数组来存储每个线程的局部变量副本,并通过AtomicInteger为每个FastThreadLocal实例分配一个唯一的索引值。
这使得访问和修改线程局部变量的操作可以通过数组索引直接完成,时间复杂度接近O(1),提高了访问速度。
而ThreadLocal则使用哈希表(通过线性探测法解决哈希冲突)来存储数据,访问效率相对较低。
避免线性探测:ThreadLocalMap在解决哈希冲突时采用线性探测法,这在高并发场景下可能会导致性能下降。而FastThreadLocal通过数组索引访问的方式避免了这一问题。
2. 内存管理优化
对象池化:FastThreadLocal使用对象池来管理线程局部变量的实例,减少了频繁创建和销毁对象的开销,降低了垃圾回收的压力。
避免弱引用问题:ThreadLocalMap的键是弱引用(WeakReference),这虽然有助于防止内存泄漏,
但在ThreadLocal对象被垃圾回收后,其对应的Entry中的value仍然可能无法被及时回收(如果线程还在运行)。
而FastThreadLocal通过其他机制(如显式的remove操作或内部清理机制)来管理内存,避免了这一问题。
3. 线程支持优化
FastThreadLocalThread:Netty提供了专门的线程类FastThreadLocalThread,它内部持有InternalThreadLocalMap实例,用于存储线程私有变量。
当使用FastThreadLocalThread时,可以充分发挥FastThreadLocal的性能优势。而使用普通Java线程时,FastThreadLocal的性能优势可能无法完全体现。
InternalThreadLocalMap
FastThreadLocal的核心是InternalThreadLocalMap类,它类似于JDK中的ThreadLocalMap
InternalThreadLocalMap使用数组来存储每个线程的局部变量副本,并通过AtomicInteger生成唯一的索引值(index),用于快速访问和修改线程局部变量的值。
每个FastThreadLocal实例在创建时都会分配一个唯一的索引值,该值作为数组的下标,用于在InternalThreadLocalMap中存取数据。
FastThreadLocal的get()和set()操作的时间复杂度可以达到O(1),极大地提升了性能。
FastThreadLocalThread
Netty通过继承Java的Thread类,实现了FastThreadLocalThread。
FastThreadLocalThread是Netty专门设计的线程类,它持有一个InternalThreadLocalMap实例,用于存储该线程的所有线程私有变量。
只有当FastThreadLocal与FastThreadLocalThread组合使用时,才能发挥出其性能优势。
初始化与赋值
在FastThreadLocal的构造过程中,会调用InternalThreadLocalMap.nextVariableIndex()方法来获取一个唯一的索引值(index)。
这个索引值被用作数组下标,用于在InternalThreadLocalMap中存取数据。
public FastThreadLocal() {
index = InternalThreadLocalMap.nextVariableIndex();
}
上一篇
下一篇
中证A500指数
JDK future 与 netty future promise 实例
netty整体架构笔记
grep 日志搜索技巧
flink jar包上传目录设置
netty NioEventLoop 性能优化与最佳实践