ThreadLocal详解

ThreadLocal:线程局部变量。线程局部变量会将共享变量拷贝一份到当前线程中,保证了变量初始值的共享,线程之间变量的隔离,以及单个线程内的数据共享。

使用ThreadLocal

以JDBC Connection为例,每个dao都需要一个Connection对象用于进行数据库操作。因为Dao在Spring中是单例的,所以属性Connection可能会被多个线程访问,但是Connection并不是线程安全的。使用ThreadLocal可以很好的解决问题,每个线程在使用Connection时,拷贝一份Connection对象,各自使用各自的,从而避免了共享变量引发的线程安全问题:

public final class ConnectionUtil {

    private ConnectionUtil() {}

    private static final ThreadLocal<Connection> conn = new ThreadLocal<>();

    public static Connection getConn() {
        Connection con = conn.get();
        if (con == null) {
            try {
                Class.forName("com.mysql.jdbc.Driver");
                con = DriverManager.getConnection("url", "userName", "password");
                conn.set(con);
            } catch (ClassNotFoundException | SQLException e) {
                // ...
            }
        }
        return con;
    }
}

ThreadLocal源码分析

ThreadLocal主要拥有以下几个方法,下面从这几个方法作为切入点分析tl的源码:

先看set方法:

所以,在线程设置一个共享变量到ThreadLocal中时,会将变量设置到Thread对象的threadLocals(是一个map)属性中。

再来看get以及remove方法:

所以,ThreadLocal变量本质上是将变量存储在当前线程Thread对象的thredLocals属性中的,此属性类型是ThreadLocal的内部类ThreadLocalMap,存放的变量key为threadLocal对象,set、get、remove本质上都是对这个map进行操作。

现在我们再看ThreadLocalMap类:

ThreadLocal是如何保证数据隔离的

ThreadLocal的隔离特性完全依赖线程之间的不可见性。具体请参考JMM(Java内存模型)。

ThreadLocal内存泄漏

参考

最后更新于

这有帮助吗?