CodeQL 文档

DateFormat 的线程不安全使用

ID: java/thread-unsafe-dateformat
Kind: problem
Security severity: 
Severity: warning
Precision: medium
Tags:
   - reliability
   - correctness
   - concurrency
Query suites:
   - java-security-and-quality.qls

单击以在 CodeQL 仓库中查看查询

应避免使用 java.text.DateFormat 类型或其后代的静态字段,因为 DateFormat 类不是线程安全的。

建议

使用实例字段,并在必要时同步访问。

示例

在以下示例中,DateFormattingThread 声明了一个类型为 DateFormat 的静态字段 dateF。当 DateFormatThreadUnsafe 创建和运行 DateFormattingThread 的实例时,会输出错误的结果,因为 dateF 由所有 DateFormattingThread 实例共享。

class DateFormattingThread implements Runnable {
    public static DateFormat dateF = new SimpleDateFormat("yyyyMMdd");  // Static field declared

    public void run() {
        for(int i=0; i < 10; i++){
            try {
                Date d = dateF.parse("20121221");
                System.out.println(d);
            } catch (ParseException e) { }
        }
    }
}

public class DateFormatThreadUnsafe {
    
    public static void main(String[] args) {
        for(int i=0; i<100; i++){
            new Thread(new DateFormattingThread()).start();
        }
    }

}

在以下对上述示例的修改中,DateFormattingThread 声明了一个类型为 DateFormat实例字段 dateF。当 DateFormatThreadUnsafeFix 创建和运行 DateFormattingThread 的实例时,会输出正确的结果,因为每个 DateFormattingThread 实例都有一个单独的 dateF 实例。

class DateFormattingThread implements Runnable {
    private DateFormat dateF = new SimpleDateFormat("yyyyMMdd");  // Instance field declared

    public void run() {
        for(int i=0; i < 10; i++){
            try {
                Date d = dateF.parse("20121221");
                System.out.println(d);
            } catch (ParseException e) { }
        }
    }
}

public class DateFormatThreadUnsafeFix {
    
    public static void main(String[] args) {
        for(int i=0; i<100; i++){
            new Thread(new DateFormattingThread()).start();
        }
    }

}

参考

  • ©GitHub, Inc.
  • 条款
  • 隐私