繁体   English   中英

Java文件通过多个线程以及多个进程锁定的方式

[英]Java file locking way by multiple threads as well as multiple processes

我有3个以上的Java进程访问同一文件进行读写。 每个进程都有多个线程,这些线程非常频繁地读写文件(在1秒钟内大约10倍的速率)。

我正在使用java.nio.channels.FileLock进行进程间文件锁定。 commonObj.wait() commonObj.notify()用于线程间同步。

我在此实施过程中面临的问题是-

  1. java.io.IOException: Resource deadlock avoided异常发生的过程之一。
  2. 进程的文件读取器线程之一获取空文件可能是因为其他某个线程或进程正在写入文件。

我的问题是

  1. 如果线程在读取或写入完成后立即释放文件锁定,那么为什么会发生问题1?
  2. 如果文件在读取或写入之前被所有进程的每个线程锁定,那么为什么会发生2个问题?

我已经为所有Java进程编写了通用的Reader writer类。 附加相同。

 package json_file_handler; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.OverlappingFileLockException; import java.util.concurrent.locks.ReentrantLock; import org.apache.log4j.Logger; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; public class JsonReader { final static Logger logger = Logger.getLogger(JsonReader.class); static final ReentrantLock relock = new ReentrantLock(); /** * Read given file in JSONObject * @param fileName String * @return JSONObject */ @SuppressWarnings("resource") public static JSONObject readJsonFile(String fileName) { JSONObject createdJsonObj = null; JSONParser jsonParser = new JSONParser(); FileChannel channel = null; FileLock lock = null; FileReader fileReader = null; boolean islocked = false; try { while(!islocked) { try { File file = new File(fileName); channel = new RandomAccessFile(file, "rw").getChannel(); lock = channel.lock(); if(lock != null) { islocked = true; fileReader = new FileReader(fileName); createdJsonObj = (JSONObject) jsonParser.parse(fileReader); } } catch(OverlappingFileLockException e) { logger.error("FILE LOCK OVERLAP EXP OCCURED IN READING FILE " + fileName +". ATTEMPTING TO READ FILE AGAIN."); //Thread.sleep(1); //release the lock if(lock != null) { lock.release(); } // close the channel if(channel != null) { channel.close(); } synchronized (relock) { relock.wait(); } } } //while } catch (FileNotFoundException e) { e.printStackTrace(); logger.error("FILE NOT FOUND ERROR IN READING JSON FOR FILE NAMED "+fileName+".",e); } catch (IOException e) { e.printStackTrace(); logger.error("IO ERROR IN READING JSON FOR FILE NAMED "+fileName+".",e); } catch (ParseException e) { e.printStackTrace(); logger.error("PARSING ERROR IN JSON FOR FILE NAMED "+fileName+".",e); } catch (Exception e) { e.printStackTrace(); logger.error("ERROR IN JSON FOR FILE NAMED "+fileName+".",e); } finally { try { if(fileReader != null) { fileReader.close(); } // release the lock if(lock != null) lock.release(); // close the channel if(channel != null) { channel.close(); } } catch (IOException e) { e.printStackTrace(); logger.error("IO ERROR IN CLOSING FILE "+fileName+".",e); } catch (Exception e) { e.printStackTrace(); logger.error("ERROR IN CLOSING FILE "+fileName+".",e); } finally { synchronized (relock) { relock.notify(); } } } return createdJsonObj; } } 

 package json_file_handler; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.OverlappingFileLockException; import org.apache.log4j.Logger; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class JsonWriter { final static Logger logger = Logger.getLogger(JsonWriter.class); /** * Write given JSONObject into given file name * @param fileName String * @param ObjToWrite JSONObejct * @return boolean true on success else false */ @SuppressWarnings("resource") public static boolean writeJsonFile(String fileName, JSONObject ObjToWrite) { boolean writeFlag = false; FileChannel channel = null; FileLock lock = null; FileWriter fileWriter = null; boolean islocked = false; try { while(!islocked) { try { File file = new File(fileName); channel = new RandomAccessFile(file, "rw").getChannel(); lock = channel.lock(); if(lock != null) { islocked = true; fileWriter = new FileWriter(fileName); Gson gson2 = new GsonBuilder().setPrettyPrinting().create(); String json2 = gson2.toJson(ObjToWrite); fileWriter.write(json2); writeFlag = true; } } catch(OverlappingFileLockException e) { logger.error("FILE LOCK OVERLAP EXP OCCURED IN WRITING FILE " + fileName +". ATTEMPTING TO WRITE FILE AGAIN."); //release the lock if(lock != null) { lock.release(); } // close the channel if(channel != null) { channel.close(); } synchronized (JsonReader.relock) { JsonReader.relock.wait(); } } } } catch (FileNotFoundException e) { e.printStackTrace(); logger.error("FILE NOT FOUND ERROR IN WRITING JSON FOR FILE NAMED "+fileName+".",e); } catch (IOException e) { e.printStackTrace(); logger.error("IO ERROR IN WRITING JSON FOR FILE NAMED "+fileName+".",e); } catch (Exception e) { e.printStackTrace(); logger.error("ERROR IN JSON FOR FILE NAMED "+fileName+".",e); } finally { try { if(fileWriter != null) { fileWriter.flush(); fileWriter.close(); } // release the lock if(lock != null) lock.release(); // close the channel if(channel != null) { channel.close(); } } catch (IOException e) { e.printStackTrace(); logger.error("IO ERROR IN CLOSING FILE "+fileName+".",e); } catch (Exception e) { e.printStackTrace(); logger.error("ERROR IN CLOSING FILE "+fileName+".",e); } finally { synchronized (JsonReader.relock) { JsonReader.relock.notify(); } } } return writeFlag; } } 

我认为您正在Linux上运行此程序。 Java将(主要)使用POSIX锁http://www.man7.org/linux/man-pages/man2/fcntl.2.html

请参阅手册中提及EDEADLK的部分。 linux操作系统很可能无法识别在同一个JVM中正在运行2个不同的线程。 请参阅https://gist.github.com/harrah/4714661此处的类似示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM