常见的线程不安全类:
- StringBuilder:线程不安全,效率高;
- StringBuffer:线程安全,使用synchronized做了处理,效率较builder低;
在一个方法内部,定义局部变量使用,属于堆栈封闭,只有单个线程可以操作这个变量,不涉及线程安全问题。
也就是说,在方法内部使用的话StringBuilder和StringBuffer都是线程安全的,建议使用StringBuilder因为其效率较高。
只有将StringBuilder定义成静态成员变量使用的时候,会造成线程安全问题。(多个线程使用一个变量)
- SimpleDateFormate:线程不安全,
- JodaTime:线程安全(日期转换 推荐使用)
使用SimpleDateFormate的时候,一定要new SimpleDateFormate()到方法内,使用局部变量堆栈封闭的方式,保证其线程安全,否则多线程访问静态成员变量,会抛出异常。
线程不安全的写法:
- 先检查在执行 if(condition(a)){handle(a);}
判断和hanle()是原子操作,不可分割,现在两个操作分开执行,如果a对象是一个多线程共享的对象,就会导致线程不安全。
注意:1、使用静态成员变量的时候,会导致多个线程共享同一个变量导致线程安全问题;
2、使用静态方法时,如果静态方法不涉及到对静态成员变量的处理,是不会导致线程安全问题的;
3、使用实例成员变量,
当类是单例的,多个线程对一个实例变量修改会导致线程安全问题
(如 springMVC的控制器对象)
(已亲测spring-boot中service是单例的,其成员变量只会实例化一次,
会导致线程安全问题,所以以后service中,成员变量要慎用)
当类是非单例的,多个线程实例化不同对象,不会导致线程安全问题(如Struts2的控制器对象)。
非单例的类的成员变量,要考虑其是否不同线程实例化不同对象,
像将该类实例化在方法内就不会造成线程安全问题。
4、使用方法内局部变量,属于堆栈封闭,不会导致线程安全问题。