Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is writer an atomic method?

I want to write some strings to a file. So, I used BufferedWriter class. Since many threads tend to write to that file, I want to know whether write and writeLine methods are atomic or not.

Also, I want the program to write the output to multiple files, and 100 lines per file (say file.txt0,file.txt1,...). For example

public class Main {
    static ExecutorService exec = Executors.newFixedThreadPool(5);
    BufferedWriter bw;
    public class myWriter implements Runnable {
        String str;
        myWriter (String str) {
            this.str = str;
        }
        public void run() {
            bw.write(str);
            bw.writeLine();
        }
    }
    public static void main(String[] args) {
        bw = new BufferedWriter(new  FileWriter("train.txt"));
        for (String arg: args)
            exec.execute(new myWriter(arg));
        exec.awaitTermination(100000, TimeUnit.MILLISECONDS);
    }
}

Can someone help me? If they are not atomic, how can I make them atomic and avoid collision?

like image 391
orezvani Avatar asked Mar 01 '12 07:03

orezvani


2 Answers

Nope, those are not atomic.

If you want multliple writes to the same file, use FileLocks.

try {
    // Get a file channel for the file
    File file = new File("filename");
    FileChannel channel = new RandomAccessFile(file, "rw").getChannel();

    // Use the file channel to create a lock on the file.
    // This method blocks until it can retrieve the lock.
    FileLock lock = channel.lock();

    // Try acquiring the lock without blocking. This method returns
    // null or throws an exception if the file is already locked.
    try {
        lock = channel.tryLock();
    } catch (OverlappingFileLockException e) {
        // File is already locked in this thread or virtual machine
    }

    // Release the lock
    lock.release();

    // Close the file
    channel.close();
} catch (Exception e) {
}
like image 110
Marcelo Avatar answered Nov 15 '22 08:11

Marcelo


The code below is source code from jdk6, it's the implementation of write in BufferedWriter,cause there's a synchronized in the function body, I think the write() in BufferedWriter is thread safe. Btw, write(String) is implemented by calling write(String,int,int).

public void write(String s, int off, int len) throws IOException {

    synchronized (lock) {

        ensureOpen();

        int b = off, t = off + len;

        while (b < t) {

            int d = min(nChars - nextChar, t - b);
            s.getChars(b, b + d, cb, nextChar);
            b += d;
            nextChar += d;

            if (nextChar >= nChars)
                flushBuffer();
            }
        }
    }
}
like image 38
NGloom Avatar answered Nov 15 '22 08:11

NGloom