静态变量在多线程中的使用问题

1、现象:问题描述

    用户登陆门户网站页面后,通过SSOsingle sign on)访问另一个网站,如果此Session超时,用户再进行操作会提示:必须先登陆才允许操作,但是当用户点击页面的返回按钮时,返回的页面并非用户最开始登陆的门户网站页面。

2、关键过程:根本原因分析

    经过代码分析发现,用户通过SSO接口登陆网站时,在登陆模块的类中使用了静态属性LOGINURL来保存用户来源,如果操作出错需要返回用户所登陆的门户网站页面时,则使用该URL。如果有其它的用户也使用SSO登录,那么静态变量的值将会被不断修改,保留的只是最后一个登录用户的信息,所以导致返回页面出错。

    在jsp页面直接使用LoginWebAction.LoginURL作为跳转页面,当多个用户通过不同的门户网站登陆时,LoginURL只能记录最后一个登陆用户的来源,导致其他登陆用户跳转的URL错误。

    

3、结论:解决方案及效果

    解决办法:将用户登陆的门户网站URL保存在session中,从session中查询用户登陆来源,如果session超时,则返回统一的错误页面。

 

4、经验总结:预防措施和规范建议

    从上面的两个例子可以看出,代码实现没有考虑变量的作用范围,对一些具体业务、事务相关的变量值保存在一个其不应该出现的范围。这种不谨慎,也违反了编程规范中的要求:尽可能的使用局部变量进行运算

对于这种情况,应该严格定义变量的作用范围:

1)对全局应用有影响的变量值,保存在ServletContext中;

2)会话相关的变量值,保存在ServletSession中;

3)事务相关的变量,保存在ServletRequest中,尽量使用局部变量进行操作;

4)不随意扩大变量的影响范围。

    同样,单实例类中的类属性其实也是一个全局变量,在多线程使用时,需要注意会话、事务相关的变量不能作为单实例类的类属性存在。

 

    private static SimpleDateFormat formatter = null;   

   

    上述方法在线程中用到,同时也没有对其进行synchronized 限制,所以在同一时刻有多个线程同时执行,而此方法中引用了全局变量formatter,这样就会导致在同时执行的线程中,formatter 变量的值相互覆盖,就会出现无法预料的结果。

在此方法内部重新声明一个局部变量,问题解决。

    多线程时在线程中尽量不要引用全局静态变量,尽量通过局部变量解决问题。

 

 

你可能感兴趣的:(静态变量在多线程中的使用问题)