其神若何,月射寒江。

白盒测试之静态检查--单例多线程安全问题

上一篇 / 下一篇  2010-03-31 11:01:32 / 个人分类:白盒测试研究

这段时间我的allin01师弟发现了一个很棘手的多线程安全问题。http://blog.csdn.net/allin01/archive/2010/03/26/5419389.aspx具体可以看博客。在stuts1.X中Action都是单例来的,但是他们团队中,有些开发在action中定义了不少类的属性,导致出现了不少莫名奇妙的数据错乱问题。后来经过分析,都是由于单例的多线程安全问题造成的。

刚好最近在研究白盒测试静态扫描,于是就开发了findbugs的插件MULTITHREAD_SINGLETON,该插件能够扫描出所有的单例类,并且判断该单例类是否存在引发线程安全的属性。现在已经应用到项目中扫描开发的类,效果还不错。

下面介绍该插件的设计思路。

 

1.1         MULTITHREAD_SINGLETON

多线程在单例情况引发线程安全问题

1.1.1         作者

Author: River.liu

Date : 2010.3.30

Email :  liuhanhong@yahoo.com.cn

1.1.2         原理

1、单例类如果存在属性,如果属性是: 基本类型 非final;非基本类型 非static..

那么可能会在该单例类中的其他方法里面写该属性,在多线程情况

下会出现读写混乱。

注意struts1.xaction也是单例来的。

2、例如

public class SingletonA {

      private StringBuffer vo = new StringBuffer();

      private SingletonA(){

             

      }

 

      private static SingletonA a=null;

      public static SingletonA getInstance(){

             if(a==null){

                    a=new SingletonA();

             }

             return a;

      }

      public void setVo(StringBuffer invo){

             vo=invo;

      }

      public StringBuffer getVo(){

             return this.vo;

      }

      

}

 

 当在多线程调用该代码的情况下就会出现问题如:

 SingletonA s=SingletonA.getInstance();

 s.setVo(new StringBuffer(Thread.currentThread().getName()));

 //这里取到的值,可能是别的线程写上去的

 StringBuffer a=s.getVo();

1.1.3         开发原理

1、判断是否为单例类

>>如果该类为配置文件中MULTITHREAD_SINGLETON.parentClassSingleton指定

的子类,那么一定就是单例

>>如果配置文件中没指定

  那么就判断是否存在公开的静态方法,并且该方法返回的值是类本身

2、判断是否存在安全隐患的属性

  如果是单例。如果存在属性:基本类型final非基本类型static的属性,那么

  该属性的读写就存在安全隐患。

 基本类型目前定义为:

booleanintshortbytelongdoublefloatcharvoidjava.lang.String

 

例如:

基本类型

//安全,基本、final,因为为基本类型,永远都不会改变

  final int a=0;

//安全,因为String是不可变对象

  final String sb=”ddd”;

//不安全,基本、非final

  String sb=”ddd”;

 

 

非基本类型

  //不安全.非基本、非static

  StringBuffer sb=new StringBuffer();

//不安全,虽然sb虽然不变,但是仅仅是对象的句柄不变,对象里面的内容是可以变的,

//是可以调用append等方法改变里面的值

  final StringBuffer sb=new StringBuffer();

  //安全,非基本、static,该情况不做安全检查

  static StringBuffer sb=new StringBuffer();

1.1.4         配置说明

配置文件pluginConfig.properties在插件的jar包里面,直接修改里面的配置项目,再放回jar包就可以了。

1.1.4.1      parentClassSingleton

参数值,表示扩展该类的所有类都是单例。

多个参数值,以逗号隔开。

由于实际开发中,有不少的类虽然没有按照常规定义单例那样来定义类,但是可能会采用用缓存等机制来保证是单例。所以我们可以根据需要来自定义去设定某些类的子类都是单例。比如stuts1.X的所有继承Action类都是单例来的。

例如:

MULTITHREAD_SINGLETON.parentClassSingleton=demo.Second,org.apache.struts.action.Action

表示凡是扩展demo.Second,org.apache.struts.action.Action类的都是单例


TAG: Findbugs findbugs 线程安全 单例

 

评分:0

我来说两句

xiaohanjiang

xiaohanjiang

River.liu又名小寒江。曾经从事多年JAVA软件开发工作,这几年一直从事软件测试工作。多年来,一直致力于软件工程、软件开发、软件测试方面的研究。不喜欢自称高手,不愿意自封资深;科学研究讲究的是务实、实践。真理、真知才是硬道理。茫茫海洋,我只希望我的每个理念能游弋于业界之间。我的思想能在你的脑海中徜徉。

日历

« 2024-04-25  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 39836
  • 日志数: 52
  • 建立时间: 2009-12-15
  • 更新时间: 2011-03-14

RSS订阅

Open Toolbar