[英]Java file locking way by multiple threads as well as multiple processes
I have more then 3 java processes accessing same file for read and write. 我有3个以上的Java进程访问同一文件进行读写。 Each process has multiple threads that read and write file very frequently (at the rate of 10 times or so in 1 second).
每个进程都有多个线程,这些线程非常频繁地读写文件(在1秒钟内大约10倍的速率)。
I am using java.nio.channels.FileLock
for interprocess file locking. 我正在使用
java.nio.channels.FileLock
进行进程间文件锁定。 And commonObj.wait()
commonObj.notify()
for interthread synchronization. 和
commonObj.wait()
commonObj.notify()
用于线程间同步。
The issue I am facing in this implementation is - 我在此实施过程中面临的问题是-
java.io.IOException: Resource deadlock avoided
exception occurs in one of the process. java.io.IOException: Resource deadlock avoided
异常发生的过程之一。 My question is, 我的问题是
I have written common reader writer classes for all java processes. 我已经为所有Java进程编写了通用的Reader writer类。 Attaching the same.
附加相同。
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; } }
I think you are running this program on linux. 我认为您正在Linux上运行此程序。 The java will be using (mostly) POSIX lock http://www.man7.org/linux/man-pages/man2/fcntl.2.html
Java将(主要)使用POSIX锁http://www.man7.org/linux/man-pages/man2/fcntl.2.html
See the part where the manual mentions about EDEADLK. 请参阅手册中提及EDEADLK的部分。 The linux OS is most probably unable to identify that 2 different threads are running inside the same JVM.
linux操作系统很可能无法识别在同一个JVM中正在运行2个不同的线程。 see a similar example in https://gist.github.com/harrah/4714661 here.
请参阅https://gist.github.com/harrah/4714661此处的类似示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.