上读锁,测试写
场景:Java程序上读锁,其他程序不申请锁直接写
结果:写入失败,但是会清空文件
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
public class FileChannelDemo {
public static void writeFile(String filepath) throws IOException {
Path path = Paths.get(filepath);
if (Files.notExists(path)) {
if (Files.notExists(path.getParent())) {
Files.createDirectories(path.getParent());
}
Files.createFile(path);
}
FileOutputStream outputStream = new FileOutputStream(path.toFile());
FileChannel fileChannel = outputStream.getChannel();
ByteBuffer byteBuffer = ByteBuffer.wrap("hello world".getBytes());
fileChannel.write(byteBuffer);
// 重新拿到内容
byteBuffer.rewind();
byteBuffer.position(5);
byte[] bs = " Tom's".getBytes();
byte[] newBs = Arrays.copyOf(bs, bs.length + byteBuffer.remaining());
byteBuffer.get(newBs, bs.length, byteBuffer.remaining());
byteBuffer = ByteBuffer.wrap(newBs);
fileChannel.position(5);
fileChannel.write(byteBuffer);
fileChannel.close();
outputStream.close();
}
}
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
public class FileLockDemo {
public static final String FILEPATH = "nio-demo/lock.txt";
public static void main(String[] args) throws IOException, InterruptedException {
FileChannelDemo.writeFile(FILEPATH);
FileInputStream inputStream = new FileInputStream(FILEPATH);
FileChannel channel = inputStream.getChannel();
FileLock lock = channel.lock(0, Integer.MAX_VALUE, true);
System.out.println("文件已上锁");
Thread.sleep(10000);
ByteBuffer buffer = ByteBuffer.allocateDirect(32);
channel.read(buffer);
buffer.flip();
byte[] bs = new byte[buffer.remaining()];
buffer.get(bs);
System.out.println("文件读取完成: " + new String(bs));
lock.release();
System.out.println("锁已释放");
channel.close();
inputStream.close();
}
}
import java.io.FileOutputStream;
import java.io.IOException;
public class FileNoLockWriteDemo {
public static void main(String[] args) throws IOException {
System.out.println("准备打开文件");
FileOutputStream outputStream = new FileOutputStream(FileLockDemo.FILEPATH);
byte[] bs = "This is a joke".getBytes();
System.out.println("准备写入");
outputStream.write(bs);
System.out.println("写入完成");
}
}
java异常信息:
准备打开文件
准备写入
Exception in thread "main" java.io.IOException: 另一个程序已锁定文件的一部分,进程无法访问。
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:313)
at com.semonx.demoset.io.nio.FileNoLockWriteDemo.main(FileNoLockWriteDemo.java:13)
尝试过使用Notepad++来写文件,结果是一样的:写入失败,文件被清空
上写锁,测试写
场景:Java程序上写锁,其他程序不上锁
结果:在写的过程中,其他进程来写,有可能造成文件数据被破坏
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
public class FileWriteLockDemo {
public static final String FILEPATH = "nio-demo/lock.txt";
public static void main(String[] args) throws IOException, InterruptedException {
FileChannelDemo.writeFile(FILEPATH);
FileOutputStream outputStream = new FileOutputStream(FILEPATH);
FileChannel channel = outputStream.getChannel();
FileLock lock = channel.lock();
System.out.println("文件已上锁");
channel.write(ByteBuffer.wrap("write lock!\r\n".getBytes()));
Thread.sleep(10000);
channel.write(ByteBuffer.wrap("write lock!".getBytes()));
lock.release();
System.out.println("锁已释放");
channel.close();
outputStream.close();
}
}
推测
文件锁和普通的内存锁应该差不多,只有正确地使用锁,才能保证临界资源的安全性。如果有进程不申请锁就进行访问,是有可能破坏掉文件的。