原文来自于:zha-ge.cn/java/83

神奇!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,踩踩坑,生活才有味道嘛~

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]