多线程问题,主要是多线程执行时的顺序是随机的,无法保证同一代码的执行顺序,任意两步代码(非原子)操作都存在安全问题
以下常见的线程安全问题:
1. 锁在String
String str="a";
synchronized(str)
{
str = "b"; //str变为一个新对象,锁失效,字符的赋值是新new一个String然后赋值的
}
2. i++,使用java.util.concurrent.atomic下的原子类代替来做多线程的计数器
i++是两步,读取i的变量的值,然后更新+1,所以不安全, 使用AtomicInteger
3. HashMap,ArrayList,使用ConcurrentHashMap,CopyOnWriteArrayList代替
4.StringBuilder,使用StringBuffer代替
5. spring项目中的controller,service使用属性存储( 就是使用class的private 自定义的属性,而不是在方法内,使用变量),然后在方法内对这个private属性有写操作,引发线程不安全,spring默认bean是单例,就一个。而每一个新请求来,会用一个新线程或从线程池取一个线程,来处理,当两个请求同时到达,引起并发,第一线程刚对private属性写完,第二线程就使用了这个private属性,对象或者字符串值,导致线程不安全。可以把这个private属性想象成指针,写操作就是使指针指向其他位置,读操作就是指针当前指向位置的对象来使用,这样好理解
6. Threadlocal变量,但是在线程池中使用线程。Threadlocal的生命周期,自然的,一般的是线程结束后,自动消失,但是线程池会重复利用线程,所以Threadlocal不一定消失,会一直存在,引发线程不安全,甚至引发内存泄漏,Threadlocal引用的内存一直被引用,无法被gc回收而造成oom