ThreadLocal在Spring事务管理中的应用

  ThreadLocal是用来处理多线程并发问题的一种解决方案。ThreadLocal是的做用是提供线程的局部变量,在多线程并发环境下,提供了与其余线程隔离的局部变量。一般这样的设计的状况是由于这个局部变量是不适合放在全局变量进行同步处理的。好比在事务管理中,在service类中的涉及到事务的方法,每一个事务的上下文都应该是独立拥有数据库的connection链接的,不然在数据提交回滚过程当中就会产生冲突。java

  spring中使用ThreadLocal来设计TransactionSynchronizationManager类,实现了事务管理与数据访问服务的解耦,同时也保证了多线程环境下connection的线程安全问题。spring

DataSourceTransactionManager的实现中,doBegin()方法开启事务,咱们看下它是怎么处理connection资源的。数据库

首先从数据库链接池中得到一个connection,并构造一个connection包装类,使用这个包装类开启事务,最后经过TransactionSynchronizationManager将connection与ThreadLocal绑定,事务提交或者回滚后,解除绑定。安全

TransactionSynchronizationManager中bindResource()的实现多线程

Resource就是ThreadLocal,而这里的Map就是ThreadLocalMap的value,与当前线程关联的ThreadLocal的值。并发


ThreadLocal又是如何为每一个线程维护一个独立的局部变量的呢?this

首先在Thread类中,都会维护一个ThreadLocalMap映射表,这个映射表存储的key是ThreadLocal自己,value则是咱们存储的局部变量object。spa

ThreadLocal类中get方法和set方法的实现。线程

    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();
    }

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

 咱们再看getMap的实现设计

    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

从代码实现中能够看出,每一个线程Thread都会维护本身的ThreadLocalMap,这个map的key则是ThreadLocal类自己,而value则是咱们保存的数据。ThreadLocal在多线程中是被公共持有的,被隔离的数据实际是存放在每一个线程的ThreadLocalMap中的,只不过是经过ThreadLocal的引用获得每一个线程维护的ThreadLocalMap中的value。

相关文章
相关标签/搜索