我有一段java代码,如果不存在则在文件系统中创建一个目录。
这个应用程序是多线程的(运行2个线程),所以有时会发生检查if(!dir.exists())
为两个线程返回true,然后在内部代码中我调用dir.mkdirs()
一个返回true创建目录而另一个返回false,让我告诉你代码:
public void makePath(){
File path = new File(Main.getPath());
synchronized (this) {
if (!path.exists()) {//return true on both treads
if (path.mkdirs()) {//return true only on one thread
logger.warn("Path was not existing, just created one");
} else {//returns false only on one thread
logger.warn("Problems while creating pth");
}
}
}
}
我的初始版本没有同步块,我认为这可以解决问题,但事实并非如此。
当我使用单个线程运行时,一切都很顺利,只有一个线程,!path.exists()
只返回true一次。
答案 0 :(得分:3)
这是因为你在内部类中进行同步。
synchronized (this)
它不能是this
,它可能是此方法的一些其他对象,就像它可以是一个字段
您可以像这样更改代码:
synchronized (Foo.class)
答案 1 :(得分:2)
如果在this
上同步(任何类的当前实例定义方法),那么这不会阻止另一个实例同时运行同一个块,因为它将自行同步。您需要同步同一个对象。
E.g。
private static Object syncKey = new Object();
public void makePath() {
synchronized (syncKey) {
...
}
}
答案 2 :(得分:0)
我已修复它委派函数来创建文件或检查它们是否存在于Util。然后,可调用实例调用此方法,而不是单独创建文件
/**
* Create a directory and its sub directories in a synchronized way
*
* @param file
* @return
*/
public static synchronized boolean createDirsIfNecessary(String path) {
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
return true;
}
return false;
}