Struts的线程安全问题

一、Servlet的线程安全问题

参考:深入研究Servlet线程安全性问题

Servlet是单例的,如果Servlet有定义实例变量并且在service方法中有赋值操作,则在多线程情况下存在线程安全问题。

 

二、Struts1

Struts1使用的ActionServlet是单例的,由这一个servlet处理所有.do请求。RequestProcessor也是单例。

 

RequestProcessor的processActionCreate方法:

 

可以看到struts1的action是单例的。线程安全问题同servlet,如果action中使用不当的实例变量,就有可能存在线程安全问题。

 

 

下面是摘自http://struts.apache.org/1.x/userGuide/building_controller.html   4.4.1 Action Class Design Guidelines 部分

 

Write code for a multi-threaded environment - Our controller servlet creates only one instance of your Action class , and uses this one instance to service all requests. Thus, you need to write thread-safe Action classes. Follow the same guidelines you would use to write thread-safe Servlets. Here are two general guidelines that will help you write scalable, thread-safe Action classes:
    // 这里说的很清楚,ActionServlet只创建一个Action实例,所有对这个Action的请求都是由这个实例来处理。与写Servlet类类似。

 

    * Only Use Local Variables - The most important principle that aids in thread-safe coding is to use only local variables , not instance variables , in your Action class. Local variables are created on a stack that is assigned (by your JVM) to each request thread, so there is no need to worry about sharing them. An Action can be factored into several local methods, so long as all variables needed are passed as method parameters. This assures thread safety, as the JVM handles such variables internally using the call stack which is associated with a single Thread.

      // 在Action类中只使用局部变量,不使用实例变量。因为局部变量是放在每个线程的独立栈中的,不是共享资源不存在线程安全问题;另外传入方法的参数变量也是不存在线程安全问题。


    * Conserve Resources - As a general rule, allocating scarce resources and keeping them across requests from the same user (in the user's session) can cause scalability problems. For example, if your application uses JDBC and you allocate a separate JDBC connection for every user, you are probably going to run in some scalability issues when your site suddenly shows up on Slashdot. You should strive to use pools and release resources (such as database connections) prior to forwarding control to the appropriate View component -- even if a bean method you have called throws an exception.
      // 这里说的是-优化资源,使用池技术。一时想明白这跟线程安全有什么关系。

 

http://hi.baidu.com/niujunkai/blog/item/021964adc130660a4a36d6ab.html

总结什么代码是线程安全的、是不需要同步的。如下:
1)常量始终是线程安全的,因为只存在读操作。
2)对构造器的访问(new 操作)是线程安全的,因为每次都新建一个实例,不会访问共享的资源。
3)最重要的是:局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量。

 

 

三、Struts2

Struts2为每个请求都实例化一个Action实例(Struts2+Spring框架中,spring的bean scope="singleton"以后另看),因此不存在多线程安全问题。

 

分析如下:

开始的FilterDispatcher和Dispatcher两个是单例,但在Dispatcher的serviceAction方法中创建的ActionProxy是局部变量,即只存在于各个线程的独立栈中,不是共享资源。

代码:

 

同样在ActionProxyFactory创建Proxy过程中生成的ActionInvocation也是局部变量,只与本线程相关。

 

创建实际Action的过程在ActionInvocation中:

action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap);

// 里边最终就是一个clazz.newInstance();

 

 

 

在上面过程中值得关注的另一个与多线程有关的处理是ActionContext类

该类中用到了ThreadLocal类来维持只与本次请求相关的参数。(ThreadLocal见ThreadLocal类 )

用ActionContext.getContext()即返回该ThreadLocal类,可以通过ctx.get(ActionContext.PARAMETERS),ctx.get(ActionContext.SESSION),ctx.get(ActionContext.APPLICATION)得到对应域的参数。

 

 

另外在看源码时发现DefaultActionInvocation的createResult()方法中用到了synchronized:

 

虽然这里results有可能与其他线程共享而HashMap又不是线程安全,但这里只有get操作,没见到有存操作,为什么还需要同步?

关于HashMap不是线程安全的详解:

HashMap深入分析

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值