高分求救——文件锁。

sundream 2004-09-11 09:29:25
有多个进程操作一个xml文件,在写的时候使用文件锁使各文件操作互斥,但是我同时也希望在读的过程中将文件锁住,此时不能进行写的操作。于是写了如下程序,但是每次运行到 lock = fileStream.getChannel().lock();
就会出现如下错误提示:
java.nio.channels.NonWritableChannelException
at sun.nio.ch.FileChannelImpl.lock(FileChannelImpl.java:724)
at java.nio.channels.FileChannel.lock(FileChannel.java:865)
at test.JDomReader.main(JDomReader.java:39)

我怀疑是不是读的时候不能加独占锁呀?有没有什么方法解决读的过程中将文件锁住的问题呀!?

package test;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.channels.FileLock;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

public class JDomReader {

public static void main(String[] args){
int i = 1;
FileLock lock = null;
while(true){
try{
String f = "C:\\JDomTest.xml";

File file = new File(f);
FileInputStream fileStream = new FileInputStream(f);

lock = fileStream.getChannel().lock();
SAXBuilder builder = new SAXBuilder();
Document readDoc = builder.build(new InputStreamReader(fileStream, "UTF-16"));
Element rootElement = readDoc.getRootElement();
System.out.println("it is the " + i + "th Read");
i++;

if(fileStream != null){
fileStream.close();
}
if(lock != null){
lock.release();
}
Object obj = new Object();
synchronized(obj){
obj.wait(100);
}
} catch (JDOMException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
System.out.println("Read");
System.exit(1);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
System.out.println("Read");
System.exit(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
...全文
914 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
sundream 2004-09-13
  • 打赏
  • 举报
回复
to registered(已注册)

还要有劳兄台,根据你的意见我对程序进行了修改,如下:
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.nio.channels.FileLock;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

/**
* @author Administrator
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class JDomReader {

public static void main(String[] args){
int i = 1;
FileLock lock = null;
while(true){
try{
String f = "C:\\JDomTest.xml";

RandomAccessFile rf = new RandomAccessFile(f, "rw");
lock = rf.getChannel().lock();
FileDescriptor fd = rf.getFD();
FileInputStream fileStream = new FileInputStream(fd);

SAXBuilder builder = new SAXBuilder();
Document readDoc = builder.build(new InputStreamReader(fileStream, "UTF-16"));
i++;
if(rf != null){
rf.close();
}

if(fileStream != null){
fileStream.close();
}
if(lock != null && lock.isValid()){
lock.release();
}
Object obj = new Object();
synchronized(obj){
obj.wait(100);
}
} catch (JDOMException e1) {
// TODO Auto-generated catch block
} catch (IOException e1) {
// TODO Auto-generated catch block
} catch (InterruptedException e) {
// TODO Auto-generated catch block
}
}
}
}


但是在
if(lock != null && lock.isValid()){
lock.release();
}
中出现如下错误:
java.io.IOException: ハンドルが無効です。
at sun.nio.ch.FileChannelImpl.release0(Native Method)
at sun.nio.ch.FileChannelImpl.release(FileChannelImpl.java:791)
at sun.nio.ch.FileLockImpl.release(FileLockImpl.java:35)
at test.JDomReader.main(JDomReader.java:57)

该怎么解决呢?
sundream 2004-09-13
  • 打赏
  • 举报
回复
我的程序是多进程读写同一个文件,所以需要这些必要的处理,感谢大家的帮助!感谢你 registered(已注册)
kill8108 2004-09-13
  • 打赏
  • 举报
回复
线程中的synchronized数据共享和代码共享的确很用呀!
registered 2004-09-13
  • 打赏
  • 举报
回复
if(fileStream != null){
fileStream.close();
}
if(lock != null && lock.isValid()){
lock.release();
}
你这个写翻了
因为你已经把文件关闭了, 锁自然也就解除了
可改为
if(lock != null && lock.isValid()){
lock.release();
}
if(fileStream != null){
fileStream.close();
}

还有就是总感觉你这个程序有点不得劲
前面大家说的都有道理,如果你是单进程执行的话最好用同步
如果是只读根本没有必要加锁
加锁的目的就是为了避免其他进程"写"同一文件
主要不太理解你"有多个进程操作一个xml文件"是何打算...
registered 2004-09-12
  • 打赏
  • 举报
回复
又仔细看了一下楼主问题
如果是一个程序内多线程访问文件, 还是用同步好
文件锁解决的是不同程序之间读写同一文件的保护办法
另外如果你所有线程都在读, 没有写线程, 完全没有必要互斥或加锁
TinyJimmy 2004-09-12
  • 打赏
  • 举报
回复
呵呵, 可能不能兼容1.3哦.
如果是一个进程内多线程, 使用同步方法控制好些.

如果是多进程的并发访问, 可以新建一个同名而不同后缀的文件, 在这个文件上加锁. 完了记得要删掉
registered 2004-09-12
  • 打赏
  • 举报
回复
关键问题不是本程序读写伤害, 问题在于其他进程是否会读写同一文件,
这个除了锁文件一般是没有办法控制的

RandomAccessFile raf = new RandomAccessFile("myFile", "rw");
raf.getChannel().lock();
programdolt 2004-09-12
  • 打赏
  • 举报
回复
学习
eddygtimegod 2004-09-12
  • 打赏
  • 举报
回复
恩,我也赞成用楼上的方法,其实用魔书的方法以可以,用synchonized(this){...}
即使在读的时候也不会有脏数据,大家认为呢?
还有RandomAccessFile那里我有点不知道其用途,rgistered(已注册) 你一般怎么用啊?
vongood 2004-09-12
  • 打赏
  • 举报
回复
学习学习,顺便UP
sundream 2004-09-12
  • 打赏
  • 举报
回复
我认为registered(已注册) 是对的!明天试验一下,准备结贴了!
yinzhaohui 2004-09-12
  • 打赏
  • 举报
回复
在不同java虚拟机中不能使用文件锁,要好锁服务
redlaputa 2004-09-12
  • 打赏
  • 举报
回复
synchonized
Han7522 2004-09-12
  • 打赏
  • 举报
回复
使用同步方法控制好些.

iceny 2004-09-11
  • 打赏
  • 举报
回复
關注,幫頂
zealVampire 2004-09-11
  • 打赏
  • 举报
回复
不知道这样可以不可以
你在外部自己加一个Object monitor..
你要读取的时候就synchronized(monitor){读}
写的时候也对synchonized(monitor){写。。}

registered 2004-09-11
  • 打赏
  • 举报
回复
java 目前还不允许锁"只读通道"
FileInputStream 是只读, 所以不能锁
如果是 FileOutputStream 应该可以

这点感觉 java 的规定有点死板...

如果你非要锁的话, 就需要用到 RandomAccessFile 了...

62,623

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧