菜鸡每日一面系列打卡19天
每天一道面试题目
助力小伙伴轻松拿offer
坚持就是胜利,我们一起努力!
题目描述
什么是ThreadLocal?
题目分析
在之前的文章中曾经说过,线程安全的实现方式有三种:互斥同步,非阻塞同步,无同步方案。我们都知道(不知道的小伙伴请看【每日一面——谈谈你对synchronized关键字的理解】这篇中对线程安全的讲解),非线程安全的条件有三个:多线程环境,共享变量,没有保证共享变量的原子性、可见性、有序性。
互斥同步与非阻塞同步的解决方式都是针对第三条进行处理,保证共享变量的原子性、可见性、有序性,从而保证线程安全;而无同步方案则不同,它是针对共享变量进行处理的。本文要讲到的ThreadLocal就属于无同步方案,在面试中,ThreadLocal也是面试官考查的常客。
接下来,随菜鸡一起去看看吧。
题目解答
01
简介
细心的读者会发现,每日一面的更新是有一道逻辑线的,这也是称之为一个系列的原因。这样做的好处是,尽可能保持知识的连贯性,从而在信息碎片化的时代给大家尽可能地还原完整的知识体系。就拿最近更新的并发编程方面的文章来说,菜鸡制作了下图来梳理知识内在的逻辑线。你品,你仔细品……
逻辑关系一目了然,而本文要讲述的主要内容就是字体为白色的内容:ThreadLocal。
02
原理
一般情况下,我们创建的变量是可以被任何一个线程访问并修改的,这也就是我们提到的共享变量的概念。而ThreadLocal变量则为每个线程都设有该变量的本地副本,让每个线程绑定自己的值,没有了共享变量,也就不存在线程安全问题了。
接下来,老规矩,跟着菜鸡一起阅读源码!
public class ThreadLocal<T> {
......
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
......
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
......
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private static final int INITIAL_CAPACITY = 16;
private Entry[] table;
private int size = 0;
private int threshold; // Default to 0
......
}
}
通过源码,我们发现,ThreadLocal底层维护了一个定制化的哈希表,而get()操作(此处省略)和set()操作本质上都是在操作ThreadLocalMap。
同时,static class Entry extends WeakReference<ThreadLocal<?>>此处的弱引用值得注意,是一个可能出现内存泄漏的点。
03
示例
接下来,我们通过一个demo,来演示一下ThreadLocal的使用。
public class ThreadLocalTest implements Runnable {
private ThreadLocal<Integer> number = ThreadLocal.withInitial(() -> 0);
@Override
public void run() {
number.set((int) Thread.currentThread().getId());
System.out.println(number.get());
}
public static void main(String[] args) {
ThreadLocalTest test = new ThreadLocalTest();
for (int i = 0; i < 10; i++) {
Thread t = new Thread(test);
t.start();
}
}
}
运行结果如下:
> Task :ThreadLocalTest.main()
12
14
10
15
11
16
13
18
19
17
BUILD SUCCESSFUL in 0s
以上便是菜鸡对ThreadLocal的一些总结,供大家参考。至此,我们已经将三种解决线程安全的方法学习完毕,是时候自我总结一下啦!
相关链接
学习 | 工作 | 分享
????长按关注“有理想的菜鸡”
只有你想不到,没有你学不到