1

I have a Java servlet which calls another software (say S) over a TCP connection. This software S uses a network resource, and the output has to be retrived from a hyperlink(using wget).

Since it's the same hyperlink I need to download my result from (irrespective of the request), it results into incorrect results few requests. I basically need to lock the use of this network resource across different processes (I believe each call from the servlet is going to create a new process).

I tried to use ReentrantLock (but I guess it only works with threads and not accross processes).

Please let me know how can this be achieved.

Thanks

Leo
  • 171
  • 1
  • 4
  • 11
  • If they're running in the same container and call into the same resource, consider using [`synchronized`](http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html). Note this is applicable to _threads_. For processes, as above, look [here](http://stackoverflow.com/questions/5297813/cross-process-synchronization-in-java). – MrGomez Mar 22 '12 at 21:32
  • A normal working server should not create a process for each client. – Martijn Courteaux Mar 22 '12 at 21:35

3 Answers3

2

Here is how to do cross-process locking in Java. Adjust to your needs and add error/exception checking/handling as necessary.

// Tester 
try { 
  if (crossProcessLockAcquire(SomeClassInYourApp.class, 3000)) { 
    // Success - This process now has the lock. (Don't keep it too long.) 
  } 
  else { 
    // Fail (Timeout) - Another process still had the lock after 3 seconds. 
  } 
} finally { 
  crossProcessLockRelease(); // try/finally is very important. 
} 

// Acquire - Returns success ( true/false ) 
private static boolean crossProcessLockAcquire(final Class<?> c, final long waitMS) { 
if (fileLock == null && c != null && waitMS > 0) { 
    try { 
        long dropDeadTime = System.currentTimeMillis() + waitMS; 
        File file = new File(lockTempDir, c.getName() + ".lock"); 
        RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw"); 
        FileChannel fileChannel = randomAccessFile.getChannel(); 
        while (System.currentTimeMillis() < dropDeadTime) { 
            fileLock = fileChannel.tryLock(); 
            if (fileLock != null) { 
                break; 
            } 
            Thread.sleep(250); // 4 attempts/sec 
        } 
    } catch (Exception e) { 
        e.printStackTrace(); 
    } 
} 
return fileLock == null ? false : true; 
} 

// Release 
private static void crossProcessLockRelease() { 
if (fileLock != null) { 
    try { 
        fileLock.release(); 
        fileLock = null; 
    } catch (IOException e) { 
        e.printStackTrace(); 
    } 
} 
} 

// Some class vars and a failsafe lock release. 
private static File lockTempDir = new File(System.getProperty("java.io.tmpdir") + File.separator + "locks"); 
private static FileLock fileLock = null; 
static { 
Runtime.getRuntime().addShutdownHook(new Thread() { 
    public void run(){ 
        crossProcessLockRelease(); 
    } 
}); 
}     
Java42
  • 7,628
  • 1
  • 32
  • 50
  • This only works so long as the processes that obtain the lock are still active. If not, the lock seems to be released implicitly. In other words, if a process "died" without manually releasing the lock, this doesn't seem to work. – searchengine27 Aug 24 '15 at 20:51
0

Why are you reusing this TCP connection? If it's easy to set up, just set one up every time you need it. For example, with an HTTP request, you should just make a new request every time.

My guess is that you have something static that shouldn't be, so multiple threads are using it when they should all have their own version.

If they're expensive, consider creating one-per-thread with ThreadLocal.

If even that doesn't work, and you don't mind threads blocking, just add "synchronized" to the method that's causing the problem.

Brendan Long
  • 53,280
  • 21
  • 146
  • 188
0

The resource you are trying to lock has to support looking. It would be better if the service didn't need to be locked externally.

As a work around you can use a ServerSocket to lock a resource between processes.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130