- 什么是线程封闭?
线程不安全是因为多线程在访问共享的可变数据时,会发生数据的不一致,结果不正确,那怎么解决这个问题呢,一个是使用同步,另外,如果只有一个线程访问这个数据,就不会出现问题,所以线程封闭的解决思想就是以某种方式实现单线程访问共享数据。
- 线程封闭有哪些实现方式?
1.使用单线程。曲折的可以这么说。
2.多线程环境下,如果能保证通过某种方式访问共享变量的时候是单线程的,也可以实现。
3.Ad-hoc,我的理解是使用程序来保证这种封闭性,这种方式不好,不好写,不好维护。
4.栈封闭,也就是使用局部变量,因为局部变量的特性是属于某个线程的,也就是说线程和线程间的局部变量是独立的。但要防止对象溢出,比如一个方法内对象被发布了,封闭性就被打破。
5使用ThreadLocal。
说明:
这里我说说我对ThreadLocal的理解,他的思想是我给每个线程都一份隔离的存储变量的空间,这样线程各存和访问各的,互不影响。
ThreadLocal内部是有个类Map的结构来存储数据,ThreadLocalMap<Thread,T>, 也就是说是以当前线程为key,以数据为value,
重要的方法有三个
initialValue() 这个方法可以被重写,设置初始值
set(),设置值
get()获取值
remove(),其实随着线程的销毁ThreadLocal中的数据都会销毁,但调用这个方法会促进垃圾回收。
- 线程封闭的应用场景
1.swing的可视化组件和数据模型对象都不是线程安全的,swing通过将他们封闭到Swing的事件分发线程中来实现线程安全。
2.jdbc的connection对象,在服务器应用中,会从连接池中获取jdbc对象,使用对象处理请求,用完后返还给连接池,由于大多数请求(比如servlet)一个请求过来是单线程的同步的方式处理,并且connection返回前连接池不会将该对象分配给其他线程,所以这种连接管理模式在处理请求时隐含的将Connection对象封闭在线程中。
3.(程序控制的例子),如果能保证单线程写入volatile变量,就可以安全的在volatile变量上执行 读-改-写的非原子操作。
4(ThreadLocal)spring?
应用程序框架大量使用了ThreadLocal,J2EE容器将事务上下文与执行中的线程关联起来,当框架判断代码运行的当前是哪个事务时,只需要从这个ThreadLocal对象中读取事务上下文。这样做的好处可以避免运行的过程中需要传递事务上下文,使框架和代码耦合。
5.Integer.toString()方法使用ThreadLocal对象来保存一个12字节大小的缓冲区,因为需要每次临时都创建这样一个临时缓冲区对象,对结果格式化,其实我觉的这种场景利用了ThreadLocal的线程隔离和Map存储数据的特性。
- 和同步机制的对比
一个是冲突时时间换空间
另一个是空间换时间。
参考文章:https://blog.csdn.net/qjyong/article/details/2158097
https://www.cnblogs.com/coshaho/p/5127135.html