java面试必备之ThreadLocal

按照传统的经验,如果某个对象是非线程安全的,在多线程环境下对象的访问需要采用synchronized进行同步。但是模板类并未采用线程同步机制,因为线程同步会降低系统的并发性能,此外代码同步解决线程安全问题的挑战很大,可能会增加好几倍的实现难度。那么模板类到底采用什么方法来解决线程安全的难题呢?答案就是ThreadLocal。

ThreadLocal是什么

顾名思义,ThreadLocal不是一个线程而是一个线程的本地化对象。当工作于多线程环境中的对象采用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程分配一个独立的副本。每个线程都可以独立的改变自己的副本,而不影响其他线程的副本。

ThreadLocal的接口方法

  • void set(Object value) 设置当前线程的线程局部变量的值
  • public Object get() 返回当前线程的线程局部变量的值
  • public void remove() 删除当前线程的局部变量的值
  • protected Object initialValue() 返回当前线程局部变量的初始值

那么ThreadLocal是如何做到为每一个线程维护一份独立的变量副本的呢? 其实思路很简单,在ThreadLocal类中有一个Map,Map中的键为线程对象,值为对应线程的变量副本。我们自己就可以实现一个简单的版本如下:

一个ThreadLocal实例

ThreadLocal与线程同步机制的比较

线程同步机制通过对象的锁机制保证同一时间只有一个线程去访问变量,该变量时多个线程共享的。ThreadLocal则为每一个线程提供了一个变量副本,从而隔离了多个线程访问数据的冲突,ThreadLocal提供了线程安全的对象封装,在编写多线程代码时,可以把不安全的代码封装进ThreadLocal。概括的说,对于多线程资源共享的问题,线程同步机制采取了时间换空间的方式,访问串行化,对象共享化;而ThreadLocal采取了空间换时间的方式,访问并行化,对象独享化。

Spring中采用ThreadLocal解决线程安全的问题

我们知道一般情况下,只有无状态的bean才可以在多线程环境下共享,在spring中绝大多数的bean都可以声明为singleton作用域。就是因为spring对一些非线程安全的“状态性对象”采用了ThreadLocal进行封装,让它们成为线程安全的对象,因此有状态的bean就可能以singleton的方式在多线程中正常工作了。

下面的实例能够体现spring对有状态bean的改造思路:

上面代码由于conn是非线程安全的成员变量,因此addTopic方法是非线程安全的。下面使用ThreadLocal对该变量进行改造,使之变成线程安全的变量:

原文发布于微信公众号 - oldriver编程老司机(bclsj-cn)

原文发表时间:2018-05-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏牛肉圆粉不加葱

JVM GC 那些事(一)- JVM 运行时内存划分

对于经常使用 Spark 的人来说,如何设置 driver 或 executor 的内存大小,如何尽量减少 GC 相信不会陌生。要做好这两点,除了 Spark ...

511
来自专栏小怪聊职场

爬虫课堂(十五)|Request和Response(请求和响应)

5626
来自专栏Vamei实验室

Python补充02 Python小技巧

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢! 在这里列举一些我使用Python时积累的小...

2027
来自专栏walterlv - 吕毅的博客

XML 的 XPath 语法

2018-06-24 11:43

1202
来自专栏向治洪

Python文件夹与文件的操作

###Python文件夹与文件的操作 最近频繁的与文件操作打交道,这块比较弱,在百度上找到一篇比较不错的文章,这是原文的传送门 有关文件夹与文件的查找,删除等功...

2405
来自专栏Java编程技术

一个有关定时生产与消费的问题

按照上面的逻辑看的话,每个队列里面最多有一个元素。其实不然,因为在多线程模型中每个线程占用cpu执行的时间是按照时间片来划分的,每个线程执行完自己的时间片后会被...

821
来自专栏古时的风筝

ThreadLocal 原理和使用场景分析

ThreadLocal 不知道大家有没有用过,但至少听说过,今天主要记录一下 ThreadLocal 的原理和使用场景。 使用场景 直接定位到 Threa...

5784
来自专栏猿人谷

realloc invalid pointer错误解析

realloc invalid pointer错误 char* temp=(char*) realloc(src,sizeof(char)*100); 如上面这...

1985
来自专栏java工会

超全超简洁SSM知识点总结

21010
来自专栏FreeBuf

FlaskJinja2 开发中遇到的的服务端注入问题研究 II

0x00. 前言 本篇文章是 《Flask Jinja2 开发中遇到的的服务端注入问题研究》<点击阅读原文查看链接>续篇,我们继续研究 Flask Jinja...

2826

扫码关注云+社区

领取腾讯云代金券