Java 同步代码块

Java 同步代码块,java,multithreading,file,Java,Multithreading,File,我有一段java代码,如果不存在的话,它会在文件系统中创建一个目录。 此应用程序是多线程的(使用两个线程运行),因此有时检查如果(!dir.exists())为两个线程返回true,然后在内部代码中调用dir.mkdirs()创建目录时,一个返回true,另一个返回false,让我向您展示代码: public void makePath(){ File path = new File(Main.getPath()); synchronized (this)

我有一段java代码,如果不存在的话,它会在文件系统中创建一个目录。 此应用程序是多线程的(使用两个线程运行),因此有时检查
如果(!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()

synchronized (this) 
它不能是此
,它可以是此方法外部的其他对象,就像它可以是字段一样

您可以这样更改代码:

synchronized (Foo.class) 

如果您在
这个
(定义方法的任何类的当前实例)上同步,那么这不会阻止另一个实例同时运行同一块,因为它将在自身上同步。您需要在同一对象上同步

例如


我已经修复了将创建文件或检查文件是否存在的函数委托给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;
}

你能告诉我你是如何调用这个方法的吗?嗨,这是一个类中实现Callable的方法中的一段代码,执行器服务然后在最多2个线程的池中调用这个对象。如果你在
这个
上同步(定义该方法的任何类的当前实例),那么这并不阻止另一个实例同时运行同一个块。您需要在同一对象上同步。@JBoy您正在创建两个或多个可调用对象的实例吗?或者您只创建了一个可调用的实例,并将该实例传递给executor service?@Debojisaikia是的,线程池中放置了更多的instances。这不是一个内部类,但我想我知道您的意思mean@JBoy编辑答案后,您可以尝试如何在另一个类“静态util”中创建方法检查/创建文件和目录,并使该方法同步?因此,运行线程的实际类将不再处理文件的创建/检查,而是将其委托给此方法更好的方法是启动应用程序,因为同步将影响性能,如果可能的话,尽量不要使用同步…因此我应该将文件的创建/检查委托给另一个类“lets say a Util”上的另一个方法,并将该新方法定义为synchronized?只有当您认为它使代码更可读或更可维护时。如果在实用程序类的实例上同步,则仍必须确保在该类的同一实例上同步两个线程。或者在类本身上同步。静态方法怎么样?请参见上面的回答,这样就不需要同步util,只有将
synchronized
放在静态方法上的方法与将
synchronized(MyClass.class)
块放在方法内部的方法相同。使用同步方法而不是同步块不会获得或丢失任何东西。
    /**
 * 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;
}