程序访问共享的可变数据需要同步机制来保证线程安全性,不使用同步机制的方式就是不共享数据,将数据封闭在单个线程中,实现线程封闭(Thread Confinement)。
实现线程封闭的技术主要有以下三种:一是Ad-hoc线程封闭,这种线程封闭的职责完全由程序实现来承担,非常脆弱;二是栈封闭,栈封闭主要采用局部变量的形式,将数据封闭在方法中,但是这种针对引用类型的局部变量的封闭需要做额外的工作来阻止局部变量的的逸出;三是ThreadLocal技术,这个类使得线程中的某个值与保存的值的对象关联起来。ThreadLocalt提供了get和set等访问接口,这些方法为每个使用该变量的线程都有独立的备份,get总是返回当前执行线程在调用set时设置的最新值。
ThreadLocal对象通常用来防止对可变的单例变量或者全局变量进行共享。
Thread-local variables are often used to prevent sharing in designs based on
mutable Singletons or global variables. For example, a single-threaded applica-
tion might maintain a global database connection that is initialized at startup to
avoid having to pass a Connection to every method. Since JDBC connections
may not be thread-safe, a multithreaded application that uses a global connection
without additional coordination is not thread-safe either. By using a ThreadLocal
to store the JDBC connection, as in ConnectionHolder in Listing 3.10, each thread
will have its own connection.
private static ThreadLocal connectionHolder = new ThreadLocal() { public Connection initialValue() { return DriverManager.getConnection(DB_URL); } }; public static Connection getConnection() { return connectionHolder.get(); }
It is easy to abuse ThreadLocal by treating its thread confinement property as
a license to use global variables or as a means of creating “hidden” method argu-
ments. Like global variables, thread-local variables can detract from reusability
and introduce hidden couplings among classes, and should therefore be used
with care.