Is the writer an atomic method?

I want to write some lines to a file. So, I used the BufferedWriter class. Since many topics tend to write to this file, I want to know whether the write and writeLine methods are atomic or not.

In addition, I want the program to write the output to several files and 100 lines to a file (say, file.txt0, file.txt1, ...). for instance

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 a collision?

+6
source share
5 answers

No, they are not atomic.

If you want to write multiple times 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) { } 
+6
source

The code below is the source code from jdk6, this is an implementation of writing to BufferedWriter , calling synchronized there in the body of the function, I think 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(); } } } } 
+5
source

You can use FileLocks, but it can be expensive.

Personally, I would use a regular object lock. eg.

 synchronized(bufferedWriter) { bufferedWriter.write stuff bufferedWriter.write more stuff } 
+3
source

NGloom is right, the following dump stream of the part of the program that performs parallel access to the BufferredWriter.append() method BufferredWriter.append() Oracle JDK 7 runtime), which does not use any synchronization in the method body. It is pretty clear that the implementation of BufferredWriter.append() uses a monitor in an instance of the BufferredWriter object, so it is thread safe. However, I cannot find anything about thread safety in the corresponding java document , and thus the API does not make any such guarantees, since such implementations can vary? In addition, the fact that Writer.write() is thread safe does not interfere with another writer who wraps another OutputStream object in the same file to try to write at the same time, which is unsafe.

 ForkJoinPool-1-worker-3" daemon prio=10 tid=0x00007f358c002800 nid=0x3e66 waiting for monitor entry [0x00007f360bdfb000] java.lang.Thread.State: BLOCKED (on object monitor) at java.io.BufferedWriter.write(BufferedWriter.java:220) - waiting to lock <0x0000000760da06d8> (a java.io.OutputStreamWriter) at java.io.Writer.write(Writer.java:157) at java.io.Writer.append(Writer.java:227) at ... ForkJoinPool-1-worker-2" daemon prio=10 tid=0x00007f358c001000 nid=0x3e65 waiting for monitor entry [0x00007f360befc000] java.lang.Thread.State: BLOCKED (on object monitor) at java.io.BufferedWriter.write(BufferedWriter.java:220) - waiting to lock <0x0000000760da06d8> (a java.io.OutputStreamWriter) at java.io.Writer.write(Writer.java:157) at java.io.Writer.append(Writer.java:227) at ... 
+1
source

Yes, BufferedWriter is thread safe. See snippet below. When recording content, the synchronized block ensures stream safety.

 public void write(int c) throws IOException { synchronized (lock) { ensureOpen(); if (nextChar >= nChars) flushBuffer(); cb[nextChar++] = (char) c; } } 

enter image description here

+1
source

Source: https://habr.com/ru/post/909718/


All Articles