Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ThreadLocal的原理和内存泄漏的原因, InheritableThreadLocal用过吗和ThreadLocal的区别 #7

Open
lycying opened this issue Dec 16, 2020 · 7 comments

Comments

@lycying
Copy link
Member

lycying commented Dec 16, 2020

日期:2020-12-14
问题:ThreadLocal的原理和内存泄漏的原因, InheritableThreadLocal用过吗和ThreadLocal的区别
标签:Java | 线程间数据隔离 | 内存泄漏
问题缘由: 蚂蚁二面的问题

@lycying
Copy link
Member Author

lycying commented Dec 16, 2020

面试官你好,threadlocal是通过thread私有变量threadlocalmap来维护的,是解决线程安全的一种方法,threadlocal在threadlocalmap中作为弱引用的key,下一次gc的时候,线程不退出,threadlocalmap不会被回收,作为弱引用的key会被gc回收,而threadlocalmap中key为null的value还占用着堆区内存,如果没有手动调用threadlocal.remove会导致累积最终oom

InheritableThreadLocal在父子线程传递值的时候用到过,解决了threadlocal不能在父子线程间传值的问题

@lycying
Copy link
Member Author

lycying commented Dec 16, 2020

threadlocalmap里value没有被回收,如果不remove的话会一直存在直到thread退出

@lycying
Copy link
Member Author

lycying commented Dec 16, 2020

不过这弱不弱引用都会导致oom,开发习惯问题
和滥用static map一样
类似的流没有关闭,连接没有断开,都要手动去写这些代码,不加以注意就会出问题

@lycying
Copy link
Member Author

lycying commented Dec 16, 2020

https://github.com/alibaba/transmittable-thread-local 阿里有增强InheritableThreadLocal的类,扩展一下今天的面试题

@lycying
Copy link
Member Author

lycying commented Dec 16, 2020

内存泄漏的定义:容易出错的地方,造成了与期望不一致的结果,就是内存泄漏。 新面试八股~

@lycying
Copy link
Member Author

lycying commented Dec 16, 2020

既然Java中有了ThreadLocal类了,为什么Netty还自己创建了一个叫做FastThreadLocal的结构?

我们首先来看一下ThreadLocal的实现。

Thread类中,有一个成员变量threadLocals,存放了与本线程相关的所有自定义信息。对这个变量的定义在Thread类,而操作却在ThreadLocal类中。

问题就出在ThreadLocalMap类上,它虽然叫Map,但却没有实现Map的接口。如图,ThreadLocalMap在rehash的时候,并没有采用类似HashMap的数组+链表+红黑树的做法,它只使用了一个数组,使用开放寻址(遇到冲突,依次查找,直到空闲位置)的方法,这种方式是非常低效的。

image

由于Netty对ThreadLocal的使用非常频繁,Netty对它进行了专项的优化。它之所以快,是因为在底层数据结构上做了文章,使用常量下标对元素进行定位,而不是使用JDK默认的探测性算法。

底层的InternalThreadLocalMap对cacheline也做了相应的优化。

image

@exceptionplayer
Copy link

关于Netty的InternalThreadLocalMap,它之前用了padding类解决false sharing问题,但是随着迭代,该类增加了几个字段,所以导致总空间超过了缓存行长度,后经讨论,官方决定去掉padding,考虑到版本兼容,将在Netty5中移除。可以参考这里

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants