神奇!Java 的 ThreadLocal 居然能做到線程間資源隔離,原理竟然如此簡單!
神奇!Java 的 ThreadLocal 居然能做到线程间资源隔离,原理竟然如此简单!
讲个趣事,前段时间组里一个新同事(小白同事D),建了个登录功能的 demo,零零散散测的时候一切安好。可一到线下环境压力一上来,各种奇葩 BUG 就开始溢出屏幕:“诶?小王怎么拿到了小张的数据?”“登录 A,结果后台显示成了 B”……看那表情,绝望中透着茫然。解决问题嘛,当然是资深程序员(也就是我)出马咯。
说到线程里的“资源独立”,ThreadLocal其实早就火出圈了。可为啥它就能让每个线程都活在自己的小世界里,丝毫互不影响?这玩意到底长啥样?咱今儿就聊聊 ThreadLocal 的小秘密。
偷窥 ThreadLocal 的小把戏
我最早玩 ThreadLocal,其实是为了搞简单的“用户身份传递”:每个请求新开个线程处理,登录信息必须得准!那会儿代码大致长这样:
private static ThreadLocal<User> userHolder = new ThreadLocal<>();
public void doLogin(User u) {
userHolder.set(u);
// ……后面N层业务代码随便调userHolder.get()都安全
}
说白了,就是一根“线”上“夹带私货”:每个线程都往里面塞自己的数据,别人根本捞不到。
所以,当时看文档说 ThreadLocal 会“为每个线程维护单独的副本”,我是真懵——这玩意是咋存的呢?每个线程一份数据,互不干扰,不怕我小伙伴捣乱?
踩坑瞬间
有趣来了。那次我本来信心满满,连夜撸完代码,上线后,想当然地以为这样线程就干干净净互不干扰了。结果日志一翻:啥?我这边 set(“A”),那边居然 get() 返回也是 “A”?还以为是鬼故事。
再一查,自己偷懒用了一个 static 的变量当缓存,结果 main 线程下 set,那些线程池线程有时候还会“继承”一点旧数据。彻底傻眼。说明:
- ThreadLocal 用对了,线程之间是安全的。
- 但如果乱用 static、线程池别名、ThreadLocalMap 空指针,嗯,“鬼故事”还是能出现的。
当然,最常见的坑其实是没清掉——许多童鞋一用就 set(),处理完业务忘记 remove(),久而久之内存嗖嗖上涨,泄露警告吓人一跳。
探个究竟:ThreadLocal 储物柜,线程专供
后来仔细扒源码,才发现 ThreadLocal 其实机智得很。每个 Thread 对象里,悄悄藏着个 ThreadLocalMap —— 说白了,每个线程私自背着个储物柜,钥匙只有自己有。
简单脑补下大致流程:
// ThreadLocal.set() 的大致真相
Thread currentThread = Thread.currentThread();
ThreadLocalMap map = currentThread.threadLocals;
map.put(this, value); // “this”就是那个ThreadLocal对象本身
- 每个线程有个“储物柜”(Map)
- 储物柜的数据:key是ThreadLocal对象,value是你的数据
- 你set的内容,只有当前线程能 get 到。其它线程?not your business
这么一想,ThreadLocal 跟平时那种共享变量刚好反过来:不是“大家都用一块”,而是“人人有份、各拿各的”。再也不怕线程间“你拿我的我拿你的”手忙脚乱了。
经验启示
经历这些踩坑,我自觉总结了几条 ThreadLocal 的黑魔法指引:
| 建议 | 说明 |
|---|---|
| 用完要记得清 | 强烈建议 finally 里 ThreadLocal.remove() |
| 切忌滥用 static | 静态变量要谨慎搭配,多线程下要分清作用域 |
| 线程池要小心 | 池化线程可能“带病上岗”,变量没清干净要出事 |
| 尽量别存大对象 | 大对象泄露难排查,ThreadLocal 最适合存小料而已 |
有时候想想,ThreadLocal 就像每个人私藏抽屉,有人贪心塞满不收拾,终究自己倒霉。朋友们不用焦虑,踩过两三次坑,你就能碰巧走进 ThreadLocal 的正确套路啦~
尾巴(聊天时间)
好啦,不知不觉又水了这么长。ThreadLocal 不是什么黑科技,但真解决了不少“线程乱穿”这类大麻烦。建议新人们:
- 慢慢扣源码、view 一下 Thread 里的 threadLocals 字段;
- 自己多写点小 demo,一遍遍 set/get/remove;
- 有空多多踩坑,掉坑越多,心就越大。
聊到这儿,今天就先收工。要是你也在“线程穿越”世界迷了路,不妨狠狠玩一把 ThreadLocal,踩踩坑,生活才有味道嘛~
共同學(xué)習(xí),寫下你的評論
評論加載中...
作者其他優(yōu)質(zhì)文章