A java thread which calls lock.release() on a lock that was locked by a different java thread will not, in fact, cause the underlying linux OS to release the lock despite the fact that at the java level, the lock is apparently released. The linux OS does not release the lock because the two java threads are mapped to two separate linux process. On linux a lock can only be released by the same process that holds the lock. A second process cannot release a lock held by a different process. On solaris and windows OS, the behaviour is different. A java thread which calls lock.release() on a lock that was locked by a different java thread will cause the underlying OS to release the lock.
This behaviour is exhibited by the following code:
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.nio.channels.*;
import javax.swing.*;
//************************************************************************//
//
// class FileLocktest
//
//************************************************************************//
public class FileLockTest implements Runnable
{ private RandomAccessFile raf = null;
private FileLock lock = null;
private FileChannel channel = null;
private int count = 0;
//The run method will release the lock and then attempt to reclaim it.
public void run(){
System.out.println("Thread 2: gonna release " + lock);
try{
lock.release();
System.out.println("Check validity of lock"+lock+"in thread 2:"+lock.isValid());
}catch(Exception e){e.printStackTrace();}
try
{ lock = channel.tryLock(0,20,false);
}
catch (Exception e) { System.out.println("ERROR: IN LOCK()"+e.getMessage());
e.printStackTrace(); }
System.out.println("Thread 2 lock = " + lock);
}
public FileLockTest()
{ //
// open file test.dat
//
try
{ raf = new RandomAccessFile(new File("test.dat"),"rw");
channel = raf.getChannel();
raf.seek(0);
raf.writeBytes("Test Test Test Test Test");
}
catch (Exception e)
{ e.printStackTrace();
Runtime.getRuntime().exit(1);
}
//lock the lock
try
{ lock = channel.tryLock(0,20,false);
}
catch (Exception e) { System.out.println("ERROR: IN LOCK()"+e.getMessage());
e.printStackTrace(); }
System.out.println("Main Thread lock = " + lock);
//Start a new thread which is this object
Thread t = new Thread(this);
try{t.start(); t.join();}catch(Exception e){};
// run();
try
{ lock = channel.tryLock(0,20,false);
}
catch (Exception e) { System.out.println("ERROR: IN LOCK()"+e.getMessage());
e.printStackTrace(); }
System.out.println("Main thread lock = " + lock);
System.exit(0);
}
public static void main( String[] args )
{ new FileLockTest();
}
}
Generates the output:
Main Thread lock = sun.nio.ch.FileLockImpl[0:20 exclusive valid]
Thread 2: gonna release sun.nio.ch.FileLockImpl[0:20 exclusive valid]
Check validity of locksun.nio.ch.FileLockImpl[0:20 exclusive invalid]in thread 2:false
Thread 2 lock = null
Main thread lock = sun.nio.ch.FileLockImpl[0:20 exclusive valid]
In the output, the 'Check validity of lock...' line is printed after lock.release() is called in the run() method. It states that the lock is unlocked. However when thread 2 does fileChannel.tryLock(long,long,boolean), it returns null indicating that the thread2 cannot acquire an apparently released lock.
This behaviour is exhibited by the following code:
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.nio.channels.*;
import javax.swing.*;
//************************************************************************//
//
// class FileLocktest
//
//************************************************************************//
public class FileLockTest implements Runnable
{ private RandomAccessFile raf = null;
private FileLock lock = null;
private FileChannel channel = null;
private int count = 0;
//The run method will release the lock and then attempt to reclaim it.
public void run(){
System.out.println("Thread 2: gonna release " + lock);
try{
lock.release();
System.out.println("Check validity of lock"+lock+"in thread 2:"+lock.isValid());
}catch(Exception e){e.printStackTrace();}
try
{ lock = channel.tryLock(0,20,false);
}
catch (Exception e) { System.out.println("ERROR: IN LOCK()"+e.getMessage());
e.printStackTrace(); }
System.out.println("Thread 2 lock = " + lock);
}
public FileLockTest()
{ //
// open file test.dat
//
try
{ raf = new RandomAccessFile(new File("test.dat"),"rw");
channel = raf.getChannel();
raf.seek(0);
raf.writeBytes("Test Test Test Test Test");
}
catch (Exception e)
{ e.printStackTrace();
Runtime.getRuntime().exit(1);
}
//lock the lock
try
{ lock = channel.tryLock(0,20,false);
}
catch (Exception e) { System.out.println("ERROR: IN LOCK()"+e.getMessage());
e.printStackTrace(); }
System.out.println("Main Thread lock = " + lock);
//Start a new thread which is this object
Thread t = new Thread(this);
try{t.start(); t.join();}catch(Exception e){};
// run();
try
{ lock = channel.tryLock(0,20,false);
}
catch (Exception e) { System.out.println("ERROR: IN LOCK()"+e.getMessage());
e.printStackTrace(); }
System.out.println("Main thread lock = " + lock);
System.exit(0);
}
public static void main( String[] args )
{ new FileLockTest();
}
}
Generates the output:
Main Thread lock = sun.nio.ch.FileLockImpl[0:20 exclusive valid]
Thread 2: gonna release sun.nio.ch.FileLockImpl[0:20 exclusive valid]
Check validity of locksun.nio.ch.FileLockImpl[0:20 exclusive invalid]in thread 2:false
Thread 2 lock = null
Main thread lock = sun.nio.ch.FileLockImpl[0:20 exclusive valid]
In the output, the 'Check validity of lock...' line is printed after lock.release() is called in the run() method. It states that the lock is unlocked. However when thread 2 does fileChannel.tryLock(long,long,boolean), it returns null indicating that the thread2 cannot acquire an apparently released lock.