usamember
usamember

Reputation: 498

Thread-safe writing to the same file

I created this method to write text to the same file by multiple threads:

public static void ThreadsafeWriter(String text, String file) throws IOException {
    String nodeValue = text;
    BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
    synchronized (writer) {
        String[] words = nodeValue.split(" ");
        for (String word: words) {
            writer.write(word);
            writer.newLine();
        }
        writer.close();
    }
}

I wanted to ask if it have any errors or no, and will it cause exceptions?

Thanks!

Upvotes: 0

Views: 1706

Answers (2)

HaroldH
HaroldH

Reputation: 533

You can achieve it by synchronizing using not the writer variable, but another static variable. This way, all objects calling this method will be synchronizing using the same object, not a the new BufferedWriter each call is creating.

Example:

public class SyncExample{

 private static Object lock = new Object(); // the object for locks does not have to be anything special.

   public static void ThreadsafeWriter(String text, String file) throws IOException {
String nodeValue = text;
    BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
    synchronized (lock ) {
        String[] words = nodeValue.split(" ");
        for (String word: words) {
            writer.write(word);
            writer.newLine();
        }
       writer.close();
    }
}


}

EDIT: I just re-read your question, sorry. Take into consideration my "fix" does ignore if the file you are trying to write to is the same or different between calls. It just makes it "impossible" to write to two any files at "same time".

Upvotes: 0

yshavit
yshavit

Reputation: 43456

Your synchronized block won't do anything; this is not thread safe.

Synchronization is on a per-instance basis: synchronized (writer) means that no other monitor can enter a synchronized block on that same exact writer instance. But you just created that writer within your method, and you never publish it to another thread; no other thread will ever see that object, let alone try to enter a synchronized block on it.

You need to create something like a static map from file path to objects to lock on (and be careful about aliases and such, which may have different paths but refer to the same file). And of course, none of that will prevent another process from writing to the file.

Atomicity with files is tricky. A common technique is to write to a temporary, random file, and then move that file to the destination path.

Upvotes: 2

Related Questions