ThreadLocal 源码解读

62 阅读2分钟

ThreadLocal

线程容器,给线程绑定一个 Object 内容,后只要线程不变,可以随时 取出.。改变线程则无法取出内容

	public static void main(String[] args) {
		final ThreadLocal<String> threadlocal = new ThreadLocal<>();
		threadlocal.set("测试");
		
		String result = threadlocal.get();
		System.out.println(result);
		
		new Thread() {
			public void run() {
				String result = threadlocal.get();
				System.out.println(result);
			};
		}.start();
	}

牛客网:说说你对ThreadLocal的理解

作用

ThreadLocal,即线程变量,它将需要并发访问的资源复制多份,让每个线程拥有一份资源。 由于每个线程都拥有自己的资源副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享机制,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。

在实现上:

Thread类中声明了ThreadLocal.ThreadLocalMap类型的threadLocals变量,用于存放当前线程独占的资源。ThreadLocalMap,这是一个类似于Map的结构,用于存放键值对。

    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

ThreadLocal类还提供了set和get方法, set方法会初始化ThreadLocalMap并将其绑定到Thread.threadLocals上,从而将传入的值绑定到当前线程。在数据存储上,ThreadLocal对象本身(this)当做key,传入的值将作为键值对的value。

// 以下为自己整合的源代码、非源代码原貌
public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = t.threadLocals;
    if (map != null)
        map.set(this, value);
    else
        t.threadLocals = new ThreadLocalMap(this, firstValue);
}

get方法没有任何参数,它会以当前ThreadLocal对象(this)为key,从Thread.threadLocals中获取与当前线程绑定的数据。

// 以下为自己整合的源代码、非源代码原貌
public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = t.threadLocals;
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}
private T setInitialValue() {
    T value = null;
    Thread t = Thread.currentThread();
    ThreadLocalMap map = t.threadLocals;
    if (map != null)
        map.set(this, value);
    else
        t.threadLocals = new ThreadLocalMap(this, value);
    return value;
}

加分回答 :

ThreadLocal不能替代同步机制,两者面向的问题领域不同。 同步机制是为了同步多个线程对相同资源的并发访问,是多个线程之间进行通信的有效方式。 而ThreadLocal是为了隔离多个线程的数据共享,从根本上避免多个线程之间对共享资源(变量)的竞争,也就不需要对多个线程进行同步了。

一般情况下,如果多个线程之间需要共享资源,以达到线程之间的通信功能,就使用同步机制。 如果仅仅需要隔离多个线程之间的共享冲突,则可以使用ThreadLocal。