对java中File.mkdirs方法线程安全问题的一点探讨
2009-09-30 00:22
330 查看
mkdirs是java中用来一次创建多级目录的方法,在java.io.File类中。
我在编程中遇到这样一段代码:
if (!dest.exists()) {
dest.mkdirs();
}
if (!dest.isDirectory()) {
throw new IOException(dest.getName() + " must be a directory!");
}
该段代码所在的方法会被多个线程调用。在某些次的运行中,dest.mkdirs方法创建目录就会失败,从而造成下面的if语句里的抛异常代码被执行。
JDK 1.5 update 21中的java.io.File.mkdirs代码如下:
public boolean mkdirs() {
if (exists()) {
return false;
}
if (mkdir()) {
return true;
}
File canonFile = null;
try {
canonFile = getCanonicalFile();
} catch (IOException e) {
return false;
}
String parent = canonFile.getParent();
return (parent != null) &&
(new File(parent, fs.prefixLength(parent)).mkdirs() &&
canonFile.mkdir());
}
考察该mkdirs源码,发现在这种可能的情形中,会出问题:两个线程都调用最前面那段代码,第一个线程中要创建的目录为“dirParent/dirA”,第二个线程要创建的目录为“dirParent/dirB”(执行以前dirParent目录不存在)。这两个线程都进入mkdirs方法,两个线程都没能直接创建目录并执行到“return”语句那一行,接下来,第一个线程执行完毕并成功创建了“dirParent/dirA”目录,这时第二个线程向前推进,对mkdirs方法的递归调用由于“dirParent”目录已存在而返回false,由“&&”运算符的短路机制,“canonFile.mkdir()”语句将不会被执行,也就是说“dirB”目录并没有被创建出来,且此时mkdirs也将返回false。于是,在第二个线程中,后面的抛出异常的语句就被执行。
这样看来,mkdirs方法并不是线程安全的。针对这段程序的实际情况,我将最上面的代码改成下面这样(FileUtils是该段代码所在的类,且该段代码所在的方法为静态方法):
if (!dest.exists()) {
synchronized (FileUtils.class) {
dest.mkdirs();
}
}
if (!dest.isDirectory()) {
throw new IOException(dest.getName() + " must be a directory!");
}
这样,问题就解决了。
我在编程中遇到这样一段代码:
if (!dest.exists()) {
dest.mkdirs();
}
if (!dest.isDirectory()) {
throw new IOException(dest.getName() + " must be a directory!");
}
该段代码所在的方法会被多个线程调用。在某些次的运行中,dest.mkdirs方法创建目录就会失败,从而造成下面的if语句里的抛异常代码被执行。
JDK 1.5 update 21中的java.io.File.mkdirs代码如下:
public boolean mkdirs() {
if (exists()) {
return false;
}
if (mkdir()) {
return true;
}
File canonFile = null;
try {
canonFile = getCanonicalFile();
} catch (IOException e) {
return false;
}
String parent = canonFile.getParent();
return (parent != null) &&
(new File(parent, fs.prefixLength(parent)).mkdirs() &&
canonFile.mkdir());
}
考察该mkdirs源码,发现在这种可能的情形中,会出问题:两个线程都调用最前面那段代码,第一个线程中要创建的目录为“dirParent/dirA”,第二个线程要创建的目录为“dirParent/dirB”(执行以前dirParent目录不存在)。这两个线程都进入mkdirs方法,两个线程都没能直接创建目录并执行到“return”语句那一行,接下来,第一个线程执行完毕并成功创建了“dirParent/dirA”目录,这时第二个线程向前推进,对mkdirs方法的递归调用由于“dirParent”目录已存在而返回false,由“&&”运算符的短路机制,“canonFile.mkdir()”语句将不会被执行,也就是说“dirB”目录并没有被创建出来,且此时mkdirs也将返回false。于是,在第二个线程中,后面的抛出异常的语句就被执行。
这样看来,mkdirs方法并不是线程安全的。针对这段程序的实际情况,我将最上面的代码改成下面这样(FileUtils是该段代码所在的类,且该段代码所在的方法为静态方法):
if (!dest.exists()) {
synchronized (FileUtils.class) {
dest.mkdirs();
}
}
if (!dest.isDirectory()) {
throw new IOException(dest.getName() + " must be a directory!");
}
这样,问题就解决了。
相关文章推荐
- 对java中File.mkdirs方法线程安全问题的一点探讨
- JMeter学习-027-JMeter参数文件(脚本分发)路径问题:jmeter.threads.JMeterThread: Test failed! java.lang.IllegalArgumentException: File distributed.csv must exist and be readable解决方法
- Java线程安全问题及线程安全解决方法
- cloudera-scm-server启动时出现Caused by: java.io.FileNotFoundException: /var/lib/cloudera-scm-server/.keystore (No such file or directory)问题解决方法(图文详解)
- java.util.File 中,mkdir()方法和mkdirs()方法的区别
- java语言基础(91)——多线程(同步方法解决线程安全问题)
- Java.io.File.mkdirs()方法实例
- 黑马程序员--java中File操作的一点小问题
- java基础25 线程的常用方法、线程安全问题、死锁现象
- 使用java.io.File的renameTo方法移动文件失败的问题
- java 类File的方法: mkdir()方法与mkdirs()的区别
- 出现java.lang.UnsupportedClassVersionError: Bad version number in .class file问题的解决方法分析
- 关于java中多线程的问题的一点思考(什么情况下需要考虑到线程,以及线程安全的问题?)
- eclipse使用问题记录—Java @override报错的解决方法
- 解决IE屏蔽Java Applet问题的方法
- Java static 静态方法 并发(是否线程安全)
- 函数中使用require_once问题深入探讨 优雅的配置文件定义方法推荐
- JS方法调用括号的问题探讨
- java.lang.UnsupportedClassVersionError: Bad version number in .class file异常的处理方法
- Java中double和float精度丢失问题及解决方法