关于threadlocal

  在网上看了很多关于threadlocal的文章,感觉大部分说的都是不明其意,关于threadlocal的作用也是众说纷纭,但最多的说法是threadlocal的作用是用于解决多线程并发问题,但自己经过测试,发现并不是那么简单,所以记录下来以供自己日后复习和参考。

     首先要确定的一点是theadlocal的出现并不是为了解决并发问题的,他的作用简单来讲应该是实现线程独有的全局变量这样一个概念。ThreadLocal之所以能使得各线程有各自独立的一个对象,不是通过对什么对象的拷贝或副本来实现的,而是通过每个线程中的new 对象 的操作来创建的对象(initialValue方法),每个线程创建一个,才能保持各线程之间互不干扰。

threadlocal的set方法如下  

/**
     * Sets the current thread's copy of this thread-local variable
     * to the specified value.  Most subclasses will have no need to
     * override this method, relying solely on the {@link #initialValue}
     * method to set the values of thread-locals.
     *
     * @param value the value to be stored in the current thread's copy of
     *        this thread-local.
     */
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

createMap方法

 /**
     * Create the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the map
     * @param map the map to store.
     */
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

        可以从上面看到完全没有什么做拷贝或是副本的操作,所以如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。 具体验证如下

package EX04;

import java.util.HashMap;

public class Test {
	static ThreadLocal<HashMap<String,String>> stringLocal = new ThreadLocal<HashMap<String,String>>();
	static HashMap<String,String> map = new HashMap<String,String>();

	public static void main(String[] args) throws InterruptedException {
		stringLocal.set(map);
		System.out.println("main >>> " +stringLocal.get().get("key"));
		stringLocal.get().put("key", "value1");
		
		Thread thread1 = new Thread() {
			public void run() {
				stringLocal.set(map);
				System.out.println("thread1 >>> " + stringLocal.get().get("key"));
				stringLocal.get().put("key", "value2");
			};
		};
		
		thread1.start();
		thread1.join();
		System.out.println("main >>> " + stringLocal.get().get("key"));
	}
}
输出:

main >>> null
thread1 >>> value1
main >>> value2
可以看到同一个static变量map,主线程修改可以影响thread1线程,thread1线程也可以影响主线程,验证结束。

最后重申,threadlocal的创建不是为了解决并发问题,而是为了作为线程内的全局变量去使用,比如数据库操作,如果一个事务中涉及多个 DAO 操作,而如果这些DAO中的Connection都是独立创建的话,就没有办法完成一个事务。但是如果放在 ThreadLocal 中就可以解决这个问题,当然他额外的好处就是,在使用过程中,别的线程(用户)也无法调用或者修改这个线程里connection对象。 



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值