当前位置:首页 > 技术 >

spring为什么要用线程安全(spring是怎么保证线程安全的)

来源:原点资讯(www.yd166.com)时间:2023-11-03 11:47:18作者:YD166手机阅读>>

Spring与线程安全

Spring作为一个IOC/DI容器,帮助我们管理了许许多多的“bean”。但其实,Spring并没有保证这些对象的线程安全,需要由开发者自己编写解决线程安全问题的代码。

Spring对每个bean提供了一个scope属性来表示该bean的作用域。它是bean的生命周期。例如,一个scope为singleton的bean,在第一次被注入时,会创建为一个单例对象,该对象会一直被复用到应用结束。

  • singleton:默认的scope,每个scope为singleton的bean都会被定义为一个单例对象,该对象的生命周期是与Spring IOC容器一致的(但在第一次被注入时才会创建)。
  • prototype:bean被定义为在每次注入时都会创建一个新的对象。
  • request:bean被定义为在每个HTTP请求中创建一个单例对象,也就是说在单个请求中都会复用这一个单例对象。
  • session:bean被定义为在一个session的生命周期内创建一个单例对象。
  • application:bean被定义为在ServletContext的生命周期中复用一个单例对象。
  • websocket:bean被定义为在websocket的生命周期中复用一个单例对象。

我们交由Spring管理的大多数对象其实都是一些无状态的对象,这种不会因为多线程而导致状态被破坏的对象很适合Spring的默认scope,每个单例的无状态对象都是线程安全的(也可以说只要是无状态的对象,不管单例多例都是线程安全的,不过单例毕竟节省了不断创建对象与GC的开销)。

无状态的对象即是自身没有状态的对象,自然也就不会因为多个线程的交替调度而破坏自身状态导致线程安全问题。无状态对象包括我们经常使用的DO、DTO、VO这些只作为数据的实体模型的贫血对象,还有Service、DAO和Controller,这些对象并没有自己的状态,它们只是用来执行某些操作的。例如,每个DAO提供的函数都只是对数据库的CRUD,而且每个数据库Connection都作为函数的局部变量(局部变量是在用户栈中的,而且用户栈本身就是线程私有的内存区域,所以不存在线程安全问题),用完即关(或交还给连接池)。

有人可能会认为,我使用request作用域不就可以避免每个请求之间的安全问题了吗?这是完全错误的,因为Controller默认是单例的,一个controller对象是会被多个线程共享的,这就又回到了线程的安全问题。当然,你也可以把Controller的scope改成prototype,实际上Struts2就是这么做的,但有一点要注意,Spring MVC对请求的拦截粒度是基于每个方法的,而Struts2是基于每个类的,所以把Controller设为多例将会频繁的创建与回收对象,严重影响到了性能。

通过阅读上文其实已经说的很清楚了,Spring根本就没有对bean的多线程安全问题做出任何保证与措施。对于每个bean的线程安全问题,根本原因是每个bean自身的设计。不要在bean中声明任何有状态的实例变量或类变量,如果必须如此,那么就使用ThreadLocal把变量变为线程私有的,如果bean的实例变量或类变量需要在多个线程之间共享,那么就只能使用synchronized、lock、CAS等这些实现线程同步的方法了。

下面将通过解析ThreadLocal的源码来了解它的实现与作用,ThreadLocal是一个很好用的工具类,它在某些情况下解决了线程安全问题(在变量不需要被多个线程共享时)。

ThreadLocal

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

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

ThreadLocal中含有一个叫做ThreadLocalMap的内部类,该类为一个采用线性探测法实现的HashMap。它的key为ThreadLocal对象而且还使用了WeakReference,ThreadLocalMap正是用来存储变量副本的。

spring为什么要用线程安全,spring是怎么保证线程安全的(1)

ThreadLocal中只含有三个成员变量,这三个变量都是与ThreadLocalMap的hash策略相关的。

spring为什么要用线程安全,spring是怎么保证线程安全的(2)

唯一的实例变量threadLocalHashCode是用来进行寻址的hashcode,它由函数nextHashCode()生成,该函数简单地通过一个增量HASH_INCREMENT来生成hashcode。至于为什么这个增量为0x61c88647,主要是因为ThreadLocalMap的初始大小为16,每次扩容都会为原来的2倍,这样它的容量永远为2的n次方,该增量选为0x61c88647也是为了尽可能均匀地分布,减少碰撞冲突。

spring为什么要用线程安全,spring是怎么保证线程安全的(3)

要获得当前线程私有的变量副本需要调用get()函数。首先,它会调用getMap()函数去获得当前线程的ThreadLocalMap,这个函数需要接收当前线程的实例作为参数。如果得到的ThreadLocalMap为null,那么就去调用setInitialValue()函数来进行初始化,如果不为null,就通过map来获得变量副本并返回。

setInitialValue()函数会去先调用initialValue()函数来生成初始值,该函数默认返回null,我们可以通过重写这个函数来返回我们想要在ThreadLocal中维护的变量。之后,去调用getMap()函数获得ThreadLocalMap,如果该map已经存在,那么就用新获得value去覆盖旧值,否则就调用createMap()函数来创建新的map。

spring为什么要用线程安全,spring是怎么保证线程安全的(4)

首页 123下一页

栏目热文

spring的单例线程安全(spring是怎么保证线程安全的)

spring的单例线程安全(spring是怎么保证线程安全的)

转自:riemann_链接:http://blog.csdn.net/riemann_/article/details/...

2023-11-03 11:52:58查看全文 >>

spring线程安全问题解析(spring创建对象线程安全怎么解决)

spring线程安全问题解析(spring创建对象线程安全怎么解决)

来源:blog.csdn.net/jdk_wangtaida/article/details/88738228前言这是我...

2023-11-03 12:05:58查看全文 >>

spring创建单例怎么保证线程安全(spring怎么解决线程安全问题)

spring创建单例怎么保证线程安全(spring怎么解决线程安全问题)

问题背景这段时间在做项目的时候,考虑到Spring中的bean默认是单例模式的,那么当多个线程调用同一个bean的时候就...

2023-11-03 11:21:48查看全文 >>

spring如何处理线程安全(spring如何处理多线程问题)

spring如何处理线程安全(spring如何处理多线程问题)

Spring与线程安全Spring作为一个IOC/DI容器,帮助我们管理了许许多多的“bean”。但其实,Spring并...

2023-11-03 11:53:53查看全文 >>

如何解决spring线程安全问题(spring线程安全解决方法)

如何解决spring线程安全问题(spring线程安全解决方法)

专注于Java领域优质技术,欢迎关注作者:Java3y Java3y前言文本已收录至我的GitHub仓库,欢迎Star:...

2023-11-03 12:03:19查看全文 >>

戴口罩有必要化妆吗(长期戴口罩可以化妆吗)

戴口罩有必要化妆吗(长期戴口罩可以化妆吗)

来源:中国妇女报图集 自今年初新冠肺炎疫情暴发至今,人们戴口罩出行已成为常态,同时由“口罩脸”引发的各种皮肤问题也日益频...

2023-11-03 11:22:37查看全文 >>

戴口罩和化妆哪个更伤害皮肤(长期戴口罩化妆好还是不化妆好)

戴口罩和化妆哪个更伤害皮肤(长期戴口罩化妆好还是不化妆好)

南都讯记者李榕新冠疫情爆发后,“口罩脸”成为很多爱美人士的痛处,脸泛油光、爆痘、皮肤过敏……所有的皮肤问题都让口罩“背锅...

2023-11-03 11:36:07查看全文 >>

化妆可以整天戴口罩吗(戴口罩适合化妆吗)

化妆可以整天戴口罩吗(戴口罩适合化妆吗)

我是行走的匠人,关注我,变美不迷路。复古和开学后,肯定是口罩不离身,平时上课出门都要戴口罩,戴口罩的时候也只会露出来我们...

2023-11-03 11:33:42查看全文 >>

化妆后口罩戴上对皮肤的影响

化妆后口罩戴上对皮肤的影响

【使用化妆品后长期佩戴口罩 会对皮肤造成伤害吗】不建议大家在使用化妆后长期佩戴口罩,这可能对皮肤状况造成更为严重的伤害。...

2023-11-03 11:48:34查看全文 >>

化妆戴口罩会不会对皮肤不好(化妆后口罩戴上对皮肤的影响)

化妆戴口罩会不会对皮肤不好(化妆后口罩戴上对皮肤的影响)

国内对“新型冠状病毒”控制得不错,但出入公众场合,还是要戴口罩,估计这种情况还要持续很长时间。对需要化妆的小伙伴,经常戴...

2023-11-03 11:33:04查看全文 >>

文档排行