2 u013179958 u013179958 于 2017.12.10 14:34 提问

静态化service,dao,为什么不会引发线程安全问题

http://note.youdao.com/noteshare?id=30df1510e58c787bb414bcd3c4e49290
问题详情

9个回答

qq87419406
qq87419406   2017.12.10 16:52
已采纳

和Struts一样,Spring的Controller默认是Singleton的,这意味着每个request过来,系统都会用原有的instance去处理,这样导致了两个结果:一是我们不用每次创建Controller,二是减少了对象创建和垃圾收集的时间;由于只有一个Controller的instance,当多个线程调用它的时候,它里面的instance变量就不是线程安全的了,会发生窜数据的问题。
当然大多数情况下,我们根本不需要考虑线程安全的问题,比如dao,service等,除非在bean中声明了实例变量。因此,我们在使用spring mvc 的contrller时,应避免在controller中定义实例变量。
如:
[java] view plain copy
public class Controller extends AbstractCommandController {

......

protected ModelAndView handle(HttpServletRequest request,HttpServletResponse response,

Object command,BindException errors) throws Exception {

company = ................;

}

protected Company company;

}

在这里有声明一个变量company,这里就存在并发线程安全的问题。
如果控制器是使用单例形式,且controller中有一个私有的变量a,所有请求到同一个controller时,使用的a变量是共用的,即若是某个请求中修改了这个变量a,则,在别的请求中能够读到这个修改的内容。。

有几种解决方法:
1、在Controller中使用ThreadLocal变量
2、在spring配置文件Controller中声明 scope="prototype",每次都创建新的controller
所在在使用spring开发web 时要注意,默认Controller、Dao、Service都是单例的。

niechenhu
niechenhu   2017.12.10 15:40

private static final 本身就是线程安全的

weixin_41339885
weixin_41339885   2017.12.10 16:15

private static final 本身就是线程安全的

qq_25304749
qq_25304749   2017.12.10 17:13

和Struts一样,Spring的Controller默认是Singleton的,这意味着每个request过来,系统都会用原有的instance去处理,这样导致了两个结果:一是我们不用每次创建Controller,二是减少了对象创建和垃圾收集的时间;由于只有一个Controller的instance,当多个线程调用它的时候,它里面的instance变量就不是线程安全的了,会发生窜数据的问题。
当然大多数情况下,我们根本不需要考虑线程安全的问题,比如dao,service等,除非在bean中声明了实例变量。因此,我们在使用spring mvc 的contrller时,应避免在controller中定义实例变量。
如:
[java] view plain copy
public class Controller extends AbstractCommandController {

......

protected ModelAndView handle(HttpServletRequest request,HttpServletResponse response,

Object command,BindException errors) throws Exception {

company = ................;

}

protected Company company;

}

在这里有声明一个变量company,这里就存在并发线程安全的问题。
如果控制器是使用单例形式,且controller中有一个私有的变量a,所有请求到同一个controller时,使用的a变量是共用的,即若是某个请求中修改了这个变量a,则,在别的请求中能够读到这个修改的内容。。

有几种解决方法:
1、在Controller中使用ThreadLocal变量
2、在spring配置文件Controller中声明 scope="prototype",每次都创建新的controller
所在在使用spring开发web 时要注意,默认Controller、Dao、Service都是单例的。

qq_38397797
qq_38397797   2017.12.10 17:16

因为此线程本身是安全的

weixin_41341130
weixin_41341130   2017.12.10 18:25

因为此线程本身是安全的有几种解决方法:
1、在Controller中使用ThreadLocal变量
2、在spring配置文件Controller中声明 scope="prototype",每次都创建新的controller
所在在使用spring开发web 时要注意,默认Controller、Dao、Service都是单例的。

Class_SpringCloud
Class_SpringCloud   2017.12.10 19:13

有状态和无状态呗,只要不改变大家都能访问的变量就不会出现并发问题,如果你修改你就会遇到,单例本就是不安全的,但是我在写代码的时候不改变共享变量,所以看起来是线程安全的

qq_27718453
qq_27718453   2017.12.11 18:09

你平常调用一个函数会引发线程问题吗,除非这个函数里有共享变量,比如静态变量或全局变量。
而service,dao中是不会有人去使用静态变量或全局变量,不存在变量共享的问题,而在被调时接口上的参数是由外部传进来的,所以互不影响。

avenccssddnn
avenccssddnn   Rxr 2017.12.13 13:42

dao跟service其实对外只提供访问数据库CRUD的功能,不会涉及到多个线程 之间共享变量资源的问题,所以一般不管service,dao是不是静态化,都是线程安全的。

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!