多线程(四):ThreadLocal

一、简述

ThreadLocal可以看作是一种数据结构,底层用map来实现。

ThreadLocal为每一个线程创建一个线程本地(thread-local)的变量,每个线程都有其独有的本地变量,相互之间的操作互不影响。

在多个线程并发访问同一个变量时,为了保证数据安全,synchronized或是Lock对对象上锁,当线程持有锁,其他线程不得访问,只有当持有锁的线程执行完毕,其他线程才能够获取锁继续执行。这种线程持有锁的机制,可以看作是花费额外时间来保证并发安全。

而使用ThreadLocal,将多个线程要访问的数据放入ThreadLocal中,则多个线程在访问ThreadLocal时,会为每一个线程创建一个  ”数据副本“,每个线程只是在操作自己的数据副本,相互之间不会影响。ThreadLocal的这种机制可以看作是用额外的空间来达到数据安全的目的。

代码示例:

public class ThreadLocalDemo extends Thread {
	private static int value=3;
	ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

	@Override
	public void run() {
		threadLocal.set(value);
		int temp = threadLocal.get();
		for (int i = 0; i < 3; i++) {
			System.out.println(Thread.currentThread().getName() + " " + temp--);
		}
	}

	public static void main(String[] args) throws InterruptedException {
		ThreadLocalDemo threadLocaDemo1 = new ThreadLocalDemo();
		ThreadLocalDemo threadLocaDemo2 = new ThreadLocalDemo();
		ThreadLocalDemo threadLocaDemo3 = new ThreadLocalDemo();
		threadLocaDemo1.start();
		threadLocaDemo2.start();
		threadLocaDemo3.start();
	}
}

二、源码

ThreadLocal的源码并不复杂,在此尝试扒一下源码。

首先看ThreadLocal.java的Outline:

从方法名就能知道方法的作用是什么。另外还有一个protected方法initialValue(),可以用来返回current thread的initial value,当第一次调用get()会返回这个初始值,如果在get()之前没有set(),返回null。

在必要时可以覆写initialValue()来指定一个初始值,这样不调用set()直接get()也不会返回null:

ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
		protected Integer initialValue(){
                        //指定初始值为0
			return 0;
		}
	};

看一下set()的源码:

可以看到set()是用一个ThreadLocalMap类型的map来保存数据,以ThreadLocal对象为key,存储的数据为value。set()首先用getMap()来获取map,获取到map之后将value存入,如果map不存在新建map。

点进getMap()看一看:

getMap()返回的threadLocals是在Thread类中一个类型为ThreadLocalMap的属性。

点进createMap():

创建了一个map,将ThreadLocal对象作为key,传入的值作为value存入,并将map保存在Thread的threadLocals属性中。

再看一下get()的源码:

get()获取Thread的map,如果map不为空,继续获取Entry,再获取value;如果map为空的话,调用setInitialValue()方法,setInitialValue()是将initialValue存入map。

(ThredLocal、ThredLocalMap、Entry之间的类关系:

-------------------------------------------------------summary---------------------------------------------------------

以上,可以明了ThreadLocal数据隔离的过程:ThreadLocal好像一个壳,存储数据的其实是ThreadLocalMap,而每一个线程(Thread)都有一个独立的ThreadLocalMap(threadLocals属性),Thread和ThreadLocal通过ThreadLocalMap关联起来,每个线程(Thread)在操作ThredLocal时,操作的都是他自己的ThreadLocalMap。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值