问题
在开发过程中,我们一旦在某个类中使用一个可变的成员变量,就会涉及到线程安全问题,因为我们的类对于其他依赖使用类来说,可能是单例注入的,这就会涉及到多个线程共享操作同一个变量问题。如何解决?
遇到线程安全问题,我们首先想到的就是使用锁,万物可加锁,只要不怕慢!我们通过加锁来实现多个线程并发访问操作问题,我加锁,你就得等我解锁后才能操作。但是众所周知,加锁,必定会在多线程并发访问时造成一部分线程阻塞等待,从而产生一定的性能影响。那除了加锁,有没有其他方法来避免?答案是:有滴!我们可以使用多种方式,下面我们娓娓道来~
ThreadLocal方式
介绍
ThreadLocal从字面理解就是本地线程,全称:Thread Local Variable。换句话说,就是当前线程变量,它是一个本地线程变量,其填充的是当前线程的变量,这个变量对于其他线程来说都是封闭且隔离的。- 如何实现变量隔离这一功能?
ThreadLocal可以为每个线程创建一个自有副本,每个线程可以访问自己内部的副本变量来达到隔离效果,从而解决共享变量的线程安全问题。 ThreadLocal变量是线程内部的局部变量,在不同的线程Thread中有不同的副本,副本只能由当前Thread使用,不存在多线程共享问题。ThreadLocal一般由private static修饰,线程结束时,可回收掉ThreadLocal副本。
案例
之前在SpringBoot—集成AOP详解(面向切面编程Aspect)中的AOP编码中也是用到了ThreadLocal进行starttime变量的存储。
源码
set方法
/**
* Sets the current thread's copy of this thread-local variable
* to the specified value. Most subclasses will have no need to
* override this method, relying solely on the {@link #initialValue}
* method to set the values of thread-locals.
*
* @param value the value to be stored in the current thread's copy of
* this thread-local.
*/
public void set(T value) {
//获取当前线程
Thread t = Thread.currentThread();
//获取当前线程中的变量map
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
//若为空,则初始化当前线程的变量map,key为当前线程,map为变量
createMap(t, value);
}
/**
* Get the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param t the current thread
* @return the map
*/
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
/**
* Create the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param t the current thread
* @param firstValue value for the initial entry of the map
*/

文章介绍了在开发中遇到的线程安全问题,特别是当类中的成员变量是可变时。提出了使用ThreadLocal来解决这个问题,ThreadLocal为每个线程提供了一个变量的副本,避免了多线程共享导致的安全问题。此外,文章还提到了ThreadLocal的内存泄漏问题以及解决方案,并对比了ThreadLocal与synchronized的区别。最后,给出了ThreadLocal的使用示例和Spring中使用@Scope(prototype)注解实现Bean多例的情况。

1665

被折叠的 条评论
为什么被折叠?



