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
应避免使用 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();
}
}
}
参考¶
Java API 规范:java.text.DateFormat 同步。