Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is writting on file using bufferwriter initialized by filewriter thread safe or not?

Tags:

java

It is thread safe or not? and if so why;

this is a part of my code

BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(tempFile, true));
bufferedWriter.write(auditParameters.toString());
bufferedWriter.newLine();
bufferedWriter.flush();
bufferedWriter.close();
like image 983
Raied Raafat Avatar asked May 06 '15 15:05

Raied Raafat


1 Answers

bufferedWriter.write is synchronized, same as flush so using the same bufferedWriter from different threads is thread safe. I used the following testprogram:

public abstract class MultiThreadedOneInstanceTemplate  implements Runnable {

private AtomicInteger threadCount = new AtomicInteger();
private static BufferedWriter bufferedWriter;

public void test() throws Exception
{
    for(int i = 0; i < 8 ;i++)
    {
        Thread thread = new Thread(this, "First Test Thread " + i);
        this.threadCount.incrementAndGet();
        thread.start();
    }


    while( this.threadCount.get() > 0 )
    {
        Thread.sleep(1000);
    }
    Thread.sleep(10 * 1000);
}


public void run()
{
    exec();
    threadCount.decrementAndGet();
}


private static synchronized BufferedWriter getWriter()
{
    try{
        if( bufferedWriter == null )
        {
            bufferedWriter =  new BufferedWriter(new FileWriter("C:\\temp\\test.txt", true)); 
        }

        return bufferedWriter;
    }
    catch(Exception e)
    {
        throw new RuntimeException(e);
    }   
}
public void exec()
{
    try{
     getWriter().write("rrssds");
     getWriter().flush();

    }
    catch(Exception e)
    {
        throw new RuntimeException(e);
    }   
}
}

And http://vmlens.com generated the following trace:

com/anarsoft/agent/regression/MultiThreadedOneInstanceTemplate.run  
com/anarsoft/agent/regression/TestFileWriter.exec  
com/anarsoft/agent/regression/TestFileWriter.getWriter monitor enter (-5)
, read(com/anarsoft/agent/regression/TestFileWriter.bufferedWriter)
monitor exit ()
java/io/Writer.write  
java/io/BufferedWriter.write , read(java/io/BufferedWriter.lock)
monitor enter (1138060695)
java/io/BufferedWriter.ensureOpen 
, read(java/io/BufferedWriter.out),         read(java/io    /BufferedWriter.cb), write(java/io/BufferedWriter.nextChar), read(java/io/BufferedWriter.nChars)
monitor exit ()
com/anarsoft/agent/regression/TestFileWriter.getWriter 
monitor enter (-5)
, read(com/anarsoft/agent/regression/TestFileWriter.bufferedWriter)
monitor exit ()
java/io/BufferedWriter.flush , read(java/io/BufferedWriter.lock)
monitor enter (1138060695)
java/io/BufferedWriter.flushBuffer , read(java/io/BufferedWriter.lock)
monitor enter (1138060695)
java/io/BufferedWriter.ensureOpen 
, read(java/io/BufferedWriter.out),     read(java/io    /BufferedWriter.cb),     
write(java/nio/charset/CharsetEncoder.state), write(java/io/BufferedWriter.nextChar), read(java/nio/Buffer.limit), read(java/nio/Buffer.mark), read(java/nio/ByteBuffer.isReadOnly), write(java/nio/Buffer.position)
java/io/OutputStreamWriter.write  
java/nio/CharBuffer.wrap  
java/nio/HeapCharBuffer.<init>  
java/nio/CharBuffer.<init>  
java/nio/Buffer.<init>  
java/nio/Buffer.limit  
java/nio/Buffer.position  
java/nio/charset/CharsetEncoder.encode , read(java/io/BufferedWriter.out),     read(java/io/BufferedWriter.cb), write(java/nio/charset/CharsetEncoder.state), write(java/io/BufferedWriter.nextChar), read(java/nio/Buffer.limit), read(java/nio/Buffer.mark), read(java/nio/ByteBuffer.isReadOnly), write(java/nio/Buffer.position)
java/nio/CharBuffer.array  
java/nio/CharBuffer.arrayOffset  
java/nio/CharBuffer.arrayOffset  
java/nio/ByteBuffer.array , read(java/io/BufferedWriter.out), read(java/io /BufferedWriter.cb), write(java/nio/charset/CharsetEncoder.state), write(java/io/BufferedWriter.nextChar), read(java/nio/Buffer.limit), read(java/nio/Buffer.mark), read(java/nio/ByteBuffer.isReadOnly), write(java/nio/Buffer.position)
java/nio/ByteBuffer.arrayOffset 
, read(java/io/BufferedWriter.out), read(java/io/BufferedWriter.cb),    write(java/nio/charset/CharsetEncoder.state), write(java/io/BufferedWriter.nextChar), read(java/nio/Buffer.limit), read(java/nio/Buffer.mark), read(java/nio/ByteBuffer.isReadOnly), write(java/nio/Buffer.position)
java/nio/ByteBuffer.arrayOffset 
, read(java/io/BufferedWriter.out), read(java/io/BufferedWriter.cb), write(java/nio/charset/CharsetEncoder.state), write(java/io/BufferedWriter.nextChar), read(java/nio/Buffer.limit), read(java/nio/Buffer.mark), read(java/nio/ByteBuffer.isReadOnly), write(java/nio/Buffer.position)
java/nio/CharBuffer.arrayOffset  
java/nio/Buffer.position  
java/nio/ByteBuffer.arrayOffset , read(java/io/BufferedWriter.out),     read(java/io/BufferedWriter.cb), write(java/nio/charset/CharsetEncoder.state), write(java/io/BufferedWriter.nextChar), read(java/nio/Buffer.limit), read(java/nio/Buffer.mark), read(java/nio/ByteBuffer.isReadOnly), write(java/nio/Buffer.position)
java/nio/Buffer.position , read(java/io/BufferedWriter.out), read(java/io/BufferedWriter.cb), write(java/nio/charset/CharsetEncoder.state), write(java/io/BufferedWriter.nextChar), read(java/nio/Buffer.limit), read(java/nio/Buffer.mark), read(java/nio/ByteBuffer.isReadOnly), write(java/nio/Buffer.position)
monitor exit ()
, read(java/io/BufferedWriter.out), write(java/nio/Buffer.limit), read(java/nio/Buffer.capacity), write(java/nio/Buffer.mark), read(java/nio/ByteBuffer.isReadOnly), write(java/nio/Buffer.position)
 java/io/OutputStreamWriter.flush , read(java/io/BufferedWriter.out),     write(java/nio/Buffer.limit), read(java/nio/Buffer.capacity), write(java/nio/Buffer.mark), read(java/nio/ByteBuffer.isReadOnly), write(java/nio/Buffer.position)
 java/nio/ByteBuffer.array , read(java/io/BufferedWriter.out), write(java/nio/Buffer.limit), read(java/nio/Buffer.capacity), write(java/nio/Buffer.mark), read(java/nio/ByteBuffer.isReadOnly), write(java/nio/Buffer.position)
java/nio/ByteBuffer.arrayOffset , read(java/io/BufferedWriter.out), write(java/nio/Buffer.limit), read(java/nio/Buffer.capacity), write(java/nio/Buffer.mark), read(java/nio/ByteBuffer.isReadOnly), write(java/nio/Buffer.position)
java/io/FileOutputStream.write , read(java/io/BufferedWriter.out),     write(java/nio/Buffer.limit), read(java/nio/Buffer.capacity), write(java/nio/Buffer.mark), read(java/nio/ByteBuffer.isReadOnly), write(java/nio/Buffer.position)
monitor exit ()
, read(com/anarsoft/agent/regression    /MultiThreadedOneInstanceTemplate.threadCount)
volatile write(unknwon)

Actually you see this also in the source code:

public void  write(String str, int off, int len) throws IOException {
 synchronized (lock) {
     char cbuf[];
        if (len <= writeBufferSize) {
            if (writeBuffer == null) {
                writeBuffer = new char[writeBufferSize];
            }
            cbuf = writeBuffer;
        } else {    // Don't permanently allocate very large buffers.
            cbuf = new char[len];
        }
        str.getChars(off, (off + len), cbuf, 0);
        write(cbuf, 0, len);
    }
    }
like image 68
Thomas Krieger Avatar answered Sep 21 '22 12:09

Thomas Krieger