原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。java
码农的世界历来不缺少名词。若是没有,咱们就强行弄上几个。这些名词有垂直领域的知识缩写,也有水平领域的抽象划分。有的行云流水无比顺畅,有的晦涩难懂如便秘。程序员
在java的并发编程里,就有一个比较晦涩的名词,叫作线程封闭。在以往的技术交流中,常常有人提到这个东西。那它究竟是何方神圣,又有什么用的功效呢?编程
你去搜索一下网络上的文章,都会给你三个选项。安全
1)Ad-hoc线程封闭。bash
2)栈封闭。微信
3)ThreadLocal类。网络
这些知识,戳破了那层窗户纸,内容其实并不复杂。可怕的是这些名词,为了记住它们真是蛋碎了一地。多线程
咱们都知道,一个变量若是被多个线程所使用,势必会引入同步问题。除了同步关键字,java引入了多种技术来达到多线程的同步问题,包括wait、notify,可重入Lock,AQS等。这种编程方式会增长程序的复杂性,使得代码容易发生bug。架构
若是有一些数据,仅仅和线程有关,对线程外的数据是不可见的,那代码写起来就美好的多。实现了这种效果的技术,就统一称为线程封闭(thread confinement)。并发
这是前提。接下来咱们来看实现。
栈封闭属于强行凑概念的一个范畴,它对写代码的人实际上是不可见的,它是JVM里虚拟机栈或者本地方法栈的默认行为。其实,咱们早就知道这个结果:成员变量是线程共享的,而局部变量是线程相关的。
很简单的道理,但背后的原理须要深刻了解JVM。为了了解这个功能,咱们须要对JVM的内存区域划分有一个初步的了解。
JVM除了存储空间最大的堆,还有线程相关的,正在运行的栈。栈封闭指的就是与线程相关的栈的相关行为。
咱们也能够再往下深挖一下。
虚拟机栈上的基本数据,实际上是一种称做栈帧的东西。你能够把栈帧理解成某个方法的执行。
在每一个方法压栈后,其中存在局部变量表、操做数栈、动态链接、返回地址等信息。咱们的局部变量,其实就是存在与这些地方。因为它们的祖先,最终只会指向一个线程,因此它们的做用范围就被封闭了。
其实,java提供给开发者惟一的线程封闭API,就是ThreadLocal。
Thread类中,有一个成员变量threadLocals
,存放了与本线程相关的全部自定义信息。对这个变量的定义在Thread,而操做却在ThreadLocal类中。
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
...
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
复制代码
关于ThreadLocal的用法有不少,好比经常使用的,每一个线程生成一个线程不安全的SimpleDateFormat
。
ThreadLocal<SimpleDateFormat> sdf = new ThreadLocal<SimpleDateFormat>();
sdf.set(new SimpleDateFormat());
复制代码
关于ThreadLocal不作过多介绍,直接查看jdk源代码便可获取全部加成。
这些信息大多来源于《JAVA并发编程》一书。我特意搜索了一下Ad-hoc
这个名字的意思。
Ad-hoc模式就和之前的直连双绞线概念同样,是P2P的链接,因此没法与其它网络中的节点进行沟通,减小了干扰。 英文中做为形容词有“特别的”,“临时”的含义。
实在是没法理解为何要用到这样的命名。
这种方式,彻底靠实现者控制,因此很是脆弱。
咱们看一下这三种方式的归宿。其中一种是JVM内部实现的,原理方面的知识;Ad-hoc是告诉用户这种线程封闭式很困难的,赶忙放弃;到最后,咱们的手里就只剩下了ThreadLocal了。
我仿佛看到了ThreadLocal在胜利的招手,同时个人名词字典里又多了几个:线程封闭、栈封闭、Ad-hoc。
做者简介:小姐姐味道 (xjjdog),一个不容许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不同的味道。个人我的微信xjjdog0,欢迎添加好友,进一步交流。