簡體   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