1

I'm new in semaphore and i have any questions. I have a thread which start and read lines from text file A and write them in to other text file B. I wrote this code, but I'm not sure whether thread block critical section and sync properly. Because and others threads can operation with these files.

public static void main(String[] args)  {

            Thread thread = new Thread(new ThreadManager());
            thread.start();

      }

Thread class:

public class ThreadManager extends Thread {
      private Semaphore semaphore;

      public ThreadManager() {
            this.semaphore = new Semaphore(1);
      }

      public void run() {

            try {
                  this.semaphore.acquire();

                  BufferedReader br = null;
                  String line;
                  String fileNme = "threadLog.txt";
                  ArrayList<String> fileLines = new ArrayList<String>();
                  int numLine = 0;

                  File outFile = new File("$$$$$$$$.tmp");

                  // input
                  FileInputStream fis = null;
                  PrintWriter out = null;
                  try {
                        fis = new FileInputStream(fileNme);

                        // output
                        FileOutputStream fos = new FileOutputStream(outFile);
                        out = new PrintWriter(fos);
                  } catch (FileNotFoundException e2) {
                        // TODO Auto-generated catch block
                        e2.printStackTrace();
                  }
                  BufferedReader in = new BufferedReader(new InputStreamReader(fis));

                  try {
                        while ((line = in.readLine()) != null) {
                              fileLines.add(line);
                        }
                  } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                  }

                  if (!fileLines.isEmpty()) {
                        int middleLine = (int) Math.round(fileLines.size() / 2);
                        fileLines.add(middleLine, Thread.currentThread().getName());

                        for (int i = 0; i < fileLines.size(); i++) {
                              out.println(fileLines.get(i));
                        }

                        out.flush();
                        out.close();
                        try {
                              in.close();
                              new File(fileNme).delete();
                              outFile.renameTo(new File(fileNme));
                        } catch (IOException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                        }

                  }
                   this.semaphore.release();
            } catch (InterruptedException e3) {
                  // TODO Auto-generated catch block
                  e3.printStackTrace();
            }

      }
Fortran
  • 593
  • 4
  • 14
  • 1
    Consider using `using {...}` blocks. –  Feb 27 '15 at 07:24
  • 1
    consider using Synchronized. This will not prevent **other** code from touching the files though. – Scary Wombat Feb 27 '15 at 07:26
  • @Scary Wombat Synchronized allows only one thread of execution to access the resource at the same time. Semaphore allows up to n (you get to choose n) threads of execution to access the resource at the same time. But then Semaphore is unnecessary for my mission? – Fortran Feb 27 '15 at 07:35
  • @Fortran It's not really clear what your mission is. Would you really want more than one thread writing to the same file at the same time, for example? – Jason C Feb 27 '15 at 07:39
  • @Fortran You only specified Semaphore with 1 thread of execution, which in my mind makes for a convoluted Synchronised – Scary Wombat Feb 27 '15 at 07:41
  • This question is unclear, but it might be a duplicate of http://stackoverflow.com/questions/25548192/how-to-synchronize-file-access-in-a-java-servlet – Raedwald Feb 27 '15 at 08:00

1 Answers1

1

You cannot guarantee synchronized access to a file, given only its filename, using semaphores or synchronized blocks (or whatever). Any other thread (or process) can still open, read, or modify that file, e.g. by creating its own FileOutputStream and passing the same file name.

While you could certainly structure your code to encourage synchronized access to a file, at least within your process, you cannot guarantee it. So you'll have to make some assumptions about the possibility of other processes accessing your file, and define (and document) some rules as to how other threads can access the file and adhere to them.

It looks like you're just making a temporary file so you could also consider File.createTempFile() to reduce the possibility of the same file name being used; adding uniqueness to the file name could help.

While I could definitely go into more detail about specific options, though, your precise use isn't clear from your question, and without more information, the best I can tell you is that synchronization primitives can't be used to 100% guarantee that nothing else is accessing that file at the same time - you have to consider your situation and find a balance between providing this protection through code vs. good documentation and sticking to rules that you define.

By the way, a semaphore with 1 permit is the same as a mutex, in which case you might find that synchronized blocks provide a more appealing syntax.

Also don't forget about ReadWriteLock, another useful tool depending on your access patterns and performance requirements.

Jason C
  • 38,729
  • 14
  • 126
  • 182
  • How i can sure that other thread is accessing that file at the same time? This is my problem! – Fortran Feb 27 '15 at 08:02
  • More information: I have a thread which read and insert new lines in same file. I must synchronized that file so that no other thread is not accessing the file at the same time. Here is how i will synchronize a file record because while other threads write. – Fortran Feb 27 '15 at 08:22
  • @Fortran You should probably not be using files for this. Consider e.g. using a List instead of a file to store data in memory, perhaps one of the premade synchronized containers or protect it yourself with a ReadWriteLock or synchronized blocks. – Jason C Feb 27 '15 at 14:21