Spring的线程安全性

目录

1、Spring中的Bean默认是单例,可能存在线程安全性问题。

2、ThreadLocal解决线程安全的方式

3、ThreadLocal中的内存泄漏


参考文章

1)、聊一聊 Spring 中的线程安全性

2)、想过没有,Spring的Bean为啥默认单例?


1、Spring中的Bean默认是单例,可能存在线程安全性问题。

什么问题?----- 有状态的Bean会出现线程问题。

什么是有状态的Bean?:

  • 有状态会话bean :每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。
  • 无状态会话bean :bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。

2、ThreadLocal解决线程安全的方式

https://mp.csdn.net/console/editor/html/108565112

总体思想:

扫描二维码关注公众号,回复: 11739466 查看本文章

为线程提供一个线程私有的变量副本,这样多个线程都可以随意更改自己线程局部的变量,不会影响到其他线程。不过需要注意的是,ThreadLocal提供的只是一个浅拷贝,如果变量是一个引用类型,那么就要考虑它内部的状态是否会被改变,想要解决这个问题可以通过重写ThreadLocal的initialValue()函数来自己实现深拷贝,建议在使用ThreadLocal时一开始就重写该函数。

ThreadLocal与像synchronized这样的锁机制是不同的。首先,它们的应用场景与实现思路就不一样,锁更强调的是如何同步多个线程去正确地共享一个变量,ThreadLocal则是为了解决同一个变量如何不被多个线程共享。从性能开销的角度上来讲,如果锁机制是用时间换空间的话,那么ThreadLocal就是用空间换时间


3、ThreadLocal中的内存泄漏

我们要考虑一种会发生内存泄漏的情况

如果ThreadLocal被设置为null后,而且没有任何强引用指向它,根据垃圾回收的可达性分析算法,ThreadLocal将会被回收。

这样一来,ThreadLocalMap中就会含有key为null的Entry,而且ThreadLocalMap是在Thread中的,只要线程迟迟不结束,这些无法访问到的value会形成内存泄漏。为了解决这个问题,ThreadLocalMap中的getEntry()、set()和remove()函数都会清理key为null的Entry,以下面的getEntry()函数的源码为例。

什么是内存泄露?内存溢出?:

  • 内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。
  • 内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。

来源:内存泄露及其解决办法 --- https://zhuanlan.zhihu.com/p/69151763

猜你喜欢

转载自blog.csdn.net/Longtermevolution/article/details/108565112