线程封闭

当访问共享变量时,就要用到同步,一种避免同步的方式就是不共享数据。如果仅在单线程中使用数据,就不需要同步,这种技术被称为线程封闭

Ad-hoc线程封闭

Ad-hoc线程封闭完全由程序实现,这种线程封闭比较脆弱,因为没有任何语言特性,变量修饰符等可以将某个变量封闭到单个线程中。

对于volatile修饰变量,只要保证只能由一个线程对变量进行写入操作,其他线程只读取该共享变量的值,则可以保证线程安全。

由于Ad-hoc线程封闭的脆弱性,在程序中尽量不要使用,应该使用更强的线程封闭技术(栈封闭和ThreadLocal等)

栈封闭

栈封闭也被称为线程内部使用或线程局部使用,在栈封闭中,只有局部变量才能访问对象。在使用栈封闭时,需要主要防止对象逸出。

ThreadLocal类

ThreadLocal类可以将变量绑定到线程中。 例如在一个线程中,使用mysql事务时,开启事务和事务中所有sql的执行,以及事务的提交都需要使用同一个MySQL链接,因此在获取链接的时候,可以使用ThreadLocal类,来保证在该线程中获取的永远都是同一个链接。

public class ConnectionUtils {
    static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

    //获取链接的方法
    public static Connection getConnection() {
        /*先从ThreadLocal对象中获取,如果为空 则创建链接,并绑定到该线程上 threadLocal.set(connection);*/
        Connection connection = threadLocal.get();
        if (connection == null) {
            connection = createConnection(URL);
            threadLocal.set(connection);
        }
        return connection;
    }
}

当某个线程初次调用ThreadLocal.get方法时,就会调用initialValue来获取初始值。从概念上看,可以将ThreadLocal理解为包含了Map<Thread,T>对象,其中保存了特定于该线程的值。但ThreadLocal的实现并非如此。这些特定于线程的值保存在Thread对象中,当线程终止后这些值就会作为垃圾回收。