springboot如何保证多线程安全

  1.springboot在多线程并发访问下是怎么做的?

  我们在Controller下,一般都是@AutoWired一些Service,由于这些Service都交给了spring进行管理,因此他们单例的,对于在Controller中调用他们的方法,由于方法在JVM中属于栈操作,所以对于每一个线程来说,栈都是独立的,因此是线程安全的。 而由于Controller本身是单例模式 (非线程安全的), 这意味着每个request过来,系统都会用原有的instance去处理,这样导致了两个结果:一是我们不用每次创建Controller,二是减少了对象创建和垃圾收集的时间;由于只有一个Controller的instance,当多个线程调用它的时候,它里面的instance变量就不是线程安全的了,会发生窜数据的问题。 如果我们定义了一个全局的实例,如 private Company company = new Company(); 而在@RequestMapping方法中去用到了他, 这里就存在并发线程安全的问题。对于所有的请求request,这个company对象是相通的。 当然我们也可以用这个特性来制作访问计数器 只需要定义一个private int cout = 0; 在每一次请求后cout++;

  当然我并不推荐这么做,计数器最好用redis来操作。

  总结以上问题,不要在Controller里出现类的实例。即便加了线程安全操作,也会出现性能问题。当然无论是Controller还是Service,如果你一定要使用对象的属性,如private Company company = new Company();可以加上ThreadLocal的引用,如private ThreadLocal<Company> tc = new ThreadLocal<>();但是把这种使用的对象放进方法中初始化(即进入JVM栈中更好)。

转载自https://my.oschina.net/u/3768341/blog/1833187(如有侵权请告知,将立即删除)

2.controller在多线程下如何尽可能保证线程安全,如何取舍?

  当多个请求对controller进行请求时,它的instance的单例模式是线程不安全的,因此我们如果要保证完全的线程安全,需要对于每次请求都创建一个新的controller实例,在spring中使用@RequestScope注解定义它的作用域为requst,即一次请求即为一个实例,这样就可以保证controller层面上的线程安全。但是这样做会有一个很大的缺点,就是这种方式当并发很大时,创建bean的新实例就比重用原有的controller实例要慢许多。

  因此还有折中的办法,就是将@RequestScope设置为session级别的作用域,这样每当一次会话,spring就会创建一个controller实例,而不需要每次请求都去创建一次实例,大大提高了访问的速度,虽然这样无法保证绝对的线程安全,但是在大部分的业务逻辑上都有效的防止了线程安全的问题。

  此外,spring的作用域还有singleton(单例,也是spring默认的作用域级别,即永远使用同一个实例)、prototype(原型)、globalSession(全局)

3.总结

  Spring本身并没有解决并发访问的问题。如果bean的范围不是线程安全的(例如在controller上面的成员变量或者静态变量就是线程不安全的),但其方法包含一些您总是希望安全运行的关键代码或者使用了静态字段需要对其进行并发修改,请在该方法上使用synchronized关键字。或者使用一些有提供线程安全的集合进行相应的多线程操作。

  • 11
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值