问题
I know we can lock a file in linux using flock(). However, NFS drive might not support file lock.
I am thinking to implement some custom file lock logic in my java code, to support file lock on any drive. Can anyone suggest a good practice?
Thanks,
回答1:
File locking must be done by the operating system kernel / file system drivers, unless you're thinking of a narrower scope like just locking between the threads of a single process. There's no way all the other processes on the system will know to talk to your application to lock/unlock without them being rewritten to do so. This is even more significant when thinking about distributed locking like what NFS does (although as you note, there are many broken NFS implementations that don't do it well).
回答2:
You can create a new file yourself which you use as a lockfile (the following is an example in Java since you stated that you wanted to implement some custom file lock logic in Java):
File lockFile = new File(".filelock");
if(!lockFile.exists()){
//create lock file
boolean success = lockFile.createNewFile();
//execute some logic...
//delete lock file
lockFile.delete();
}else{
//lock file exists, cannot execute the logic that we wanted
}
回答3:
The Java Standard Library does not expose flock()
or fnctl()
directly. It seems to use lockf()
in FileChannel/FileLock - but I wouldn't count on it using lockf()
if you need to be sure. From the libraries point of view, this is an implementation details that can change.
If you actually want to use the specific posix function, take a look at jnr-posix and related projects. Here's an example how you could use it. Beware, this is basically writing low-level C in Java, but that's the goal after all, right? :)
// couldn't find these in jnr-posix...
// from http://linux.die.net/include/sys/file.h
/* Operations for the `flock' call. */
public static final int LOCK_EX = 2; /* Exclusive lock. */
public static final int LOCK_UN = 8; /* Unlock. */
/* Can be OR'd in to one of the above. */
public static final int LOCK_NB = 4; /* Don't block when locking. */
private static void throwErrno(String fn, Path path) throws IOException {
int err = posix.errno();
throw new IOException(fn + "() returned errno " + err + " '" + Errno.valueOf(err) + "' for " + path );
}
public int flock(Path path, int mode, boolean blocking) {
int fd = posix.open(path.toString(),
OpenFlags.O_WRONLY.intValue() | OpenFlags.O_CREAT.intValue(),
mode);
if (fd < 0) {
throwErrno("open", path);
}
int operation = LOCK_EX;
if (!blocking) {
operation |= LOCK_NB;
}
int ret = posix.flock(fd, operation);
if (ret != 0) {
throwErrno("flock", path);
}
return fd;
}
This is just minimal demo code. I would recommend to return an AutoClosable
that releases the log when closed.
来源:https://stackoverflow.com/questions/12537803/linux-file-locking-in-java