别轻易使用成员变量,因为多线程会导致成员变量成为共享的资源,可能导致成员变量被多个线程进行修改,不安全。

所以能使用局部变量,就使用局部变量,大部分情况下,它是线程安全的。

什么时候局部变量不安全呢?发生了逃逸,即局部变量脱离所在的作用域,出现在其他方法里被使用,可能导致子类继承父类重写该方法,导致该局部变量被其他线程共享,如下:

public abstract class Father {

    public void bar() {
        // 是否安全
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        foo(sdf);
    }

    public void foo(SimpleDateFormat sdf);

    public static void main(String[] args) {
        new Test().bar();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

一个子类继承 Test,重写 foo 方法

public class Son extends Father{
  public void foo(SimpleDateFormat sdf) {
      String dateStr = "1999-10-11 00:00:00";
      for (int i = 0; i < 20; i++) {
          new Thread(() -> {
              try {
                  sdf.parse(dateStr);
              } catch (ParseException e) {
                  e.printStackTrace();
              }
          }).start();
      }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

sdf 对象在 main 线程的 bar 方法创建,却在子类的另一个线程执行 parse 方法,所以线程不安全。

线程不安全概念:一个对象在当前线程被使用时,另一个线程也在使用该对象,导致不安全。

解决 foo 线程不安全方法(局部变量在多个方法间传递问题)就是设置方法为 private,这样就不会被子类重写。

更新时间: 2024/01/17, 05:48:13
最近更新
01
JVM调优
12-10
02
jenkins
12-10
03
Arthas
12-10
更多文章>