Possible to use as a semaphore between java applications?

1,917 views
Skip to first unread message

Marton Szucs

unread,
Aug 24, 2012, 4:37:44 AM8/24/12
to java-ch...@googlegroups.com
HI!

I want to edit files in a directory from several different applications running on the same machine.
But I want synchronize the editing process. So that only one application can edit the files. And not two or more at the same time.

If this was in a single java application I would have used a semaphore or a synchronization block.

private static Semaphore semaphore = new Semaphore(1);

public void editFiles() {
    try {
        semaphore.acquire();
        
        //Edit files
        
    } finally {
        semaphore.release();
    }
}

Is it possible to use Java Chroniclefor this but between two different java applications on the same machine?

Kind Regards

Márton

Peter Lawrey

unread,
Aug 24, 2012, 5:47:08 AM8/24/12
to java-ch...@googlegroups.com
Hello,

The way I handle this is to have only one process writing to a file at
any one time. All the other process read what the others produce. You
could implement locking this way.

I would suggest trying to ensure only one process writes to a file can
be much faster than using multiple processes writing to the same
files.

Peter.

Marton Szucs

unread,
Aug 24, 2012, 7:31:35 AM8/24/12
to java-ch...@googlegroups.com
Hi!

But how do you ensure that only one process is editing files in a directory. (I forgot to mention that it is not only editing. I also create and delete files in the directory).
I thought about using a lock-file. But is that safe?


private File sharedLockFile = new File("lockfile.lock");
private FileChannel channel;
private FileLock lock;

public void editFiles() {
    try {
        while(!lockFile()) {
         Tread.sleep(200);
      }
        
        //Create, Delete and Edit files in a directory used by other applications
        
    } finally {
        unlockFile()
    }
}

private boolean lockFile() throws IOException {

   // Check if the lock exist
   if (sharedLockFile.exists())
      // if exist try to delete it
      sharedLockFile.delete();
   // Try to get the lock
   channel = new RandomAccessFile(sharedLockFile, "rw").getChannel();
   lock = channel.tryLock();
   if (lock == null) {
      // File is locked by other application
      channel.close();
      return false;
   }
   return true;
}

public static void unlockFile() throws IOException {
   // release and delete file lock
   try {
      if (lock != null) {
         lock.release();
         channel.close();
      }
   finally {
      if (sharedLockFile != null)
         sharedLockFile.delete();
   }
}

I appreciate the help even if it does not have anything to do with Java Chronicle. You can remove my posts from this Group later if you wan't to.

// Márton

Peter Lawrey

unread,
Aug 24, 2012, 8:11:49 AM8/24/12
to java-ch...@googlegroups.com
Hello,
You could just have one process opening the files and have other
processes talk to it (e.g. via sockets) to get all the work. This
would avoid having to wait 200 ms between polling to see if the file
is locked or not. With one process accessing the files, you can use
simple resource co-ordination.
BTW: Databases often use one process to access all its data and you
talk to it via sockets.

Peter.

Marton Szucs

unread,
Aug 24, 2012, 8:27:52 AM8/24/12
to java-ch...@googlegroups.com
That would be the best option. To write from one application and send messages from the others. The full context of my problem is that I have three webapplications in Tomcat that creates and renames files in a shared directory. Because they are in different Context I can't use a ContextListener to communicate to a common "File editor".

I have looked at JMS and RMI and they seem overkill for such a simple task. That is why I started to look at Java Chronicle. I wanted to use it to send messages between application. But I could not find any example for that.
Even sockets seems overkill. But maybe a bit easier because it uses standard java libraries

I am not concerned about speed for this task so the 200ms waiting time is no problem for me :)

I don't want to use a database. Would it not involve pooling data from the database to see if something new is there?

Thank you for your help. And as I said you can remove this thread from Java Chronicle Group if you want to ;)

// Márton

Peter Lawrey

unread,
Aug 24, 2012, 9:43:04 AM8/24/12
to java-ch...@googlegroups.com
Hello,

If latency is not a problem and you don't need a journal of your
requests, I would use Sockets to request operation from a shared
service

Peter.

Laurent Caillette

unread,
Aug 25, 2012, 2:22:15 AM8/25/12
to java-ch...@googlegroups.com
Hi all,

My personal feeling is, because all applications run in the same JVM, you don't have the usual problems with multiple process, where a process may die without notifying others of its death. 

I would create a simple locking service over HTTP. If the writes are always short, this could be a very simple protocol like "block until the lock gets released". Otherwise there are standard HTTP status code like "server temporarily unavailable". You can even add locker's identifier in the HTTP response.

Sure, HTTP is overkill, but it better fits in Tomcat's architecture than raw socket creation, and it does basically the same thing.

Regards,

c;

Peter Lawrey

unread,
Aug 25, 2012, 3:02:17 AM8/25/12
to java-ch...@googlegroups.com
Hello,

Another option if you are using one JVM, is to support locking via a
shared library.
You can add a library to the container such that its only loaded once
and you can have a singleton for managing file access.
Its not a pretty solution but it could be the simplest.

Peter.

Marton Szucs

unread,
Aug 25, 2012, 1:19:28 PM8/25/12
to java-ch...@googlegroups.com
Peter: This is new for me. How do you use a shared library that is only loaded once?

// Márton
Message has been deleted

Marton Szucs

unread,
Aug 26, 2012, 3:28:08 AM8/26/12
to java-ch...@googlegroups.com
I am so sorry about my last post. It was meant to a friend. And was about tickets to a show... I have removed it now from the Google groups thread.
Now I know why he didn't answer :P

// Márton

Peter Lawrey

unread,
Aug 26, 2012, 6:25:03 AM8/26/12
to java-ch...@googlegroups.com
Hello,

I haven't done this in a while but...

With many containers, you can have libraries which are part of the
application and libraries which are part of the container (and loaded
only once)
E.g. in Tomcat there is a directory where you load the jars for
tomcat, and separate directories for each application. If you add the
library to the tomcat directory it will be shared across all
applications.

Peter.
Reply all
Reply to author
Forward
0 new messages