ThreadLocal详解,处理成员变量线程不安全的情况
ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量。
这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线程都在操作同一个变量,显然是不行的,并且我们也知道volatile这个关键字也是不能保证线程安全的。那么在有一种情况之下,我们需要满足这样一个条件:变量是同一个,但是每个线程都使用同一个初始值,也就是使用同一个变量的一个新的副本。这种情况之下ThreadLocal就非常使用,比如说DAO的数据库连接,我们知道DAO是单例的,那么他的属性Connection就不是一个线程安全的变量。而我们每个线程都需要使用他,并且各自使用各自的。这种情况,ThreadLocal就比较好的解决了这个问题。
我们从源码的角度来分析这个问题。
首先定义一个ThreadLocal:
public class ConnectionUtil {
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
private static Connection initConn = null;
static {
try {
initConn = DriverManager.getConnection("url, name and password");
} catch (SQLException e) {
e.printStackTrace();
}
}
public Connection getConn() {
Connection c = tl.get();
if(null == c) tl.set(initConn);
return tl.get();
}
}
这样子,都是用同一个连接,但是每个连接都是新的,是同一个连接的副本。
那么实现机制是如何的呢?
1、每个Thread对象内部都维护了一个ThreadLocalMap这样一个ThreadLocal的Map,可以存放若干个ThreadLocal。
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
2、当我们在调用get()方法的时候,先获取当前线程,然后获取到当前线程的ThreadLocalMap对象,如果非空,那么取出ThreadLocal的value,否则进行初始化,初始化就是将initialValue的值set到ThreadLocal中。
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
3、当我们调用set()方法的时候,很常规,就是将值设置进ThreadLocal中。
4、总结:当我们调用get方法的时候,其实每个当前线程中都有一个ThreadLocal。每次获取或者设置都是对该ThreadLocal进行的操作,是与其他线程分开的。
5、应用场景:当很多线程需要多次使用同一个对象,并且需要该对象具有相同初始化值的时候最适合使用ThreadLocal。
6、其实说再多也不如看一下源码来得清晰。如果要看源码,其中涉及到一个WeakReference和一个Map,这两个地方需要了解下,这两个东西分别是a.Java的弱引用,也就是GC的时候会销毁该引用所包裹(引用)的对象,这个threadLocal作为key可能被销毁,但是只要我们定义成他的类不卸载,tl这个强引用就始终引用着这个ThreadLocal的,永远不会被gc掉。b.和HashMap差不多。
事实上,从本质来讲,就是每个线程都维护了一个map,而这个map的key就是threadLocal,而值就是我们set的那个值,每次线程在get的时候,都从自己的变量中取值,既然从自己的变量中取值,那肯定就不存在线程安全问题,总体来讲,ThreadLocal这个变量的状态根本没有发生变化,他仅仅是充当一个key的角色,另外提供给每一个线程一个初始值。如果允许的话,我们自己就能实现一个这样的功能,只不过恰好JDK就已经帮我们做了这个事情。
ThreadLocal应用范例:
http://www.cnblogs.com/wangzhongqiu/p/7542110.html
ThreadLocal详解,处理成员变量线程不安全的情况的更多相关文章
- iava多线程详解(2)-成员变量与局部变量访问
有两段代码 1.线程访问成员变量 public class FirstThreadTest { public static void main(String[] args) { FirstThread ...
- 深入解析ThreadLocal 详解、实现原理、使用场景方法以及内存泄漏防范 多线程中篇(十七)
简介 从名称看,ThreadLocal 也就是thread和local的组合,也就是一个thread有一个local的变量副本 ThreadLocal提供了线程的本地副本,也就是说每个线程将会拥有一个 ...
- android Handler机制之ThreadLocal详解
概述 我们在谈Handler机制的时候,其实也就是谈Handler.Message.Looper.MessageQueue之间的关系,对于其工作原理我们不做详解(Handler机制详解). Messa ...
- ThreadLocal详解(实现多线程同步访问变量)
ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量. 这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线 ...
- Java并发编程:线程封闭和ThreadLocal详解
转载请标明出处: http://blog.csdn.net/forezp/article/details/77620769 本文出自方志朋的博客 什么是线程封闭 当访问共享变量时,往往需要加锁来保证数 ...
- Java中Static关键字详解以及静态变量和成员变量的区别
一.static关键字的特点 (1)修饰成员变量.成员方法(2)随着类的加载而加载(3)优先于对象存在(4)被所有对象共享(5)可以通过类名调用 它本身也可以通过对象名调用 例如:main()方法由j ...
- ThreadLocal详解
ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量. 这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线 ...
- 并发系列(2)之 ThreadLocal 详解
本文将主要结合源码讲述 ThreadLocal 的使用场景和内部结构,以及 ThreadLocalMap 的内部结构:另外在阅读文本之前只好先了解一下引用和 HashMap 的相关知识,可以参考 Re ...
- ThreadLocal详解,ThreadLocal源码分析,ThreadLocal图解
本文脉路: 概念阐释 ----> 原理图解 ------> 源码分析 ------> 思路整理 ----> 其他补充. 一.概念阐述. ThreadLocal 是一个为 ...
随机推荐
- STM32Cube自学-1
为了方便调试,使用Keil5+Proteus.1.新建Proteus STM32项目,选择STMF103C6 2.新建STM32CubeMX项目,选择同型号CPU,选择UART1,Asynchrono ...
- DotNetBar 控件设置空内容时显示内容
可以通过修改所有关于Watermark时的设置.
- golang string int int64转换
#string到int int,err:=strconv.Atoi(string) #string到int64 int64, err := strconv.ParseInt(string, 10, 6 ...
- java操作Hbase
public class Test { public Connection connection; // 用HBaseconfiguration初始化配置信息是会自动加载当前应用的classpath下 ...
- 堆叠窗口QStackedWidget
经常将QStackedWidget和QListWidget或者QListView搭配使用 import sys from PyQt5.QtWidgets import QApplication, QW ...
- JavaScript之原生接口类设计
//接口类 var Interface = function(name , methods){ if(arguments.length!=2){ ...
- HDU2444 The Accomodation of Students【匈牙利算法】
题意: 有n个学生,有m对人是认识的,每一对认识的人能分到一间房,问能否把n个学生分成两部分,每部分内的学生互不认识,而两部分之间的学生认识.如果可以分成两部分,就算出房间最多需要多少间,否则就输出N ...
- POJ1751 Highways【最小生成树】
题意: 给你N个城市的坐标,城市之间存在公路,但是由于其中一些道路损坏了,需要维修,维修的费用与公路长成正比(公路是直的). 但现有M条公路是完整的,不需要维修,下面有M行,表示不需要维修的道路两端的 ...
- python - 添加文件环境变量
#添加 当前文件目录 import sys,os BASE_DIR = os.path.dirname(os.path.dirname(__file__)) sys.path.append(BASE ...
- python - 计算器 程序练习
v1.0 计算器(数据内不含括号方式:) import re def jisuan(a,b,c): sun_count = 0 if c =="+": sun_count = st ...