Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between a singleton Class with synchronized function and a static synchronized function

I have less experience of multi-thread programming. I have multi-threads to write to a file. And I was wondering what's the difference between:

Implement 1: a class with static synchronized function. And each thread call FileUtil.writeToFile()

public class FileUtil {

    public static synchronized void writeToFile(String filename) {
        // write to file....
    }
}

Implement 2: A singleton class. And each thread call Fileutil.getInstance().writeToFile()

public class FileUtil {
    private static final FileUtil fileManager = new FileUtil();
    private FileUtil() {
    }

    public synchronized void writeToFile(String filename) {
        // write to file....
    }

    public static FileUtil getInstance() {
        return fileManager;
    }
}
like image 266
Freya Ren Avatar asked May 02 '26 13:05

Freya Ren


1 Answers

The issues in your question can be divided into:

  • Should I use a class with static methods or the singleton pattern? This has already been discussed, for example in Difference between static class and singleton pattern?.
  • Is there a difference between the two synchronizations? Well, one locks on a class, the other on an object. And as Sotirios Delimanolis linked in the comments, it's discussed in Java synchronized static methods: lock on object or class.

Regarding the choice of monitor, there is a third option:

Use a monitor object that is not accessible to the caller. The advantage of this is that if the user of the class or the singleton decides to use that class or that singleton as a monitor in his own program, it won't cause all calls to writeToFile() to be blocked.

That is, suppose somebody does this:

FileUtil obj = FileUtil.getInstance();
synchronized ( obj ) {
    // Some long operation
}

Because the writeToFile() method synchronizes on that same instance, no other thread will be able to use writeToFile() until the "long operation" is done and the synchronized block is left.

Now, instead, if you did this:

public class FileUtil {
    private static final FileUtil fileManager = new FileUtil();
    private static final Object lock = new Object(); // To be used for synchronizing

    private FileUtil() {
    }

    public void writeToFile(String filename) {
        synchronized (lock) {
            // write to file....
        }
    }

    public static FileUtil getInstance() {
        return fileManager;
    }
}

then even if the user of your class decides to use it as a lock (be it the class monitor or an instance monitor), it's not going to interfere with the functionality of writeToFile().

like image 195
RealSkeptic Avatar answered May 04 '26 02:05

RealSkeptic