2

我有更多的3個java進程訪問相同的文件進行讀寫。每個進程都有多個線程,可以非常頻繁地讀取和寫入文件(在1秒內以10次左右的速度讀寫)。多線程以及多進程的Java文件鎖定方式

我正在使用java.nio.channels.FileLock進行進程間文件鎖定。 和commonObj.wait()commonObj.notify()用於線程間同步。

我對着在此實現的問題是 - 在這個過程中的一個發生

  1. java.io.IOException: Resource deadlock avoided例外。
  2. 進程的文件讀取器線程之一獲取空文件可能是因爲某些其他線程或進程正在寫入文件。

我的問題是,

  1. 如果線程釋放文件,只要閱讀或問題的原因發生1寫入,於是做了鎖?
  2. 如果文件被讀取前的所有進程的每個線程鎖定或 寫入然後爲什麼會發生2問題?

我已經爲所有java進程編寫了通用讀寫器類。附上相同的。

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 { 
 
    
 
\t final static Logger logger = Logger.getLogger(JsonReader.class); 
 
\t static final ReentrantLock relock = new ReentrantLock(); 
 
     
 
\t /** 
 
\t * Read given file in JSONObject 
 
\t * @param fileName String 
 
\t * @return JSONObject 
 
\t */ 
 
    @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 
 
     { 
 
     \t while(!islocked) 
 
     \t { 
 
     \t \t try 
 
     \t \t { 
 
     \t \t \t File file = new File(fileName); 
 
     \t \t \t channel = new RandomAccessFile(file, "rw").getChannel(); 
 
     \t \t \t 
 
     \t \t \t lock = channel.lock(); 
 
     \t \t \t if(lock != null) 
 
     \t \t \t { 
 
     \t \t \t \t islocked = true; 
 
     \t \t \t \t fileReader = new FileReader(fileName); 
 
     \t \t \t \t createdJsonObj = (JSONObject) jsonParser.parse(fileReader); 
 
     \t \t \t } 
 
     \t \t } 
 
     \t \t catch(OverlappingFileLockException e) 
 
     \t \t { 
 
     \t \t \t logger.error("FILE LOCK OVERLAP EXP OCCURED IN READING FILE " + fileName 
 
     \t \t \t \t \t \t \t +". ATTEMPTING TO READ FILE AGAIN."); 
 
     \t \t \t //Thread.sleep(1); 
 
     \t \t \t //release the lock 
 
     \t \t \t if(lock != null) 
 
     \t \t \t { 
 
     \t \t \t \t lock.release(); 
 
     \t \t \t } 
 
     \t \t \t // close the channel 
 
     \t \t \t if(channel != null) 
 
     \t \t \t { 
 
     \t \t \t \t channel.close(); 
 
     \t \t \t } 
 
     \t \t \t synchronized (relock) { 
 
\t  \t \t \t \t relock.wait(); 
 
\t  \t \t \t } 
 
     \t \t } 
 
     \t } \t //while 
 
     } 
 
     catch (FileNotFoundException e) 
 
     { 
 
     \t 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) 
 
     { 
 
     \t e.printStackTrace(); 
 
     \t logger.error("PARSING ERROR IN JSON FOR FILE NAMED "+fileName+".",e); 
 
     } 
 
     catch (Exception e) 
 
     { 
 
     \t e.printStackTrace(); 
 
     \t logger.error("ERROR IN JSON FOR FILE NAMED "+fileName+".",e);   
 
     } 
 
     finally { 
 
      try { 
 
       if(fileReader != null) 
 
       { 
 
       \t fileReader.close(); 
 
       } 
 
       // release the lock 
 
       if(lock != null) 
 
        lock.release(); 
 
       // close the channel 
 
       if(channel != null) 
 
       { 
 
       \t 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 { 
 
      \t synchronized (relock) { 
 
    \t \t \t \t relock.notify(); 
 
    \t \t \t } 
 
\t \t \t } 
 
     } 
 
     
 
     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 { 
 
    
 
\t final static Logger logger = Logger.getLogger(JsonWriter.class); 
 
     
 
\t /** 
 
\t * Write given JSONObject into given file name 
 
\t * @param fileName String 
 
\t * @param ObjToWrite JSONObejct 
 
\t * @return boolean true on success else false 
 
\t */ 
 
    @SuppressWarnings("resource") 
 
    public static boolean writeJsonFile(String fileName, JSONObject ObjToWrite) { 
 
    \t 
 
    \t boolean writeFlag = false; 
 
    \t 
 
     FileChannel channel = null; 
 
     FileLock lock = null; 
 
     FileWriter fileWriter = null; 
 
     boolean islocked = false; 
 
     
 
     try 
 
     {   \t 
 
     \t while(!islocked) 
 
     \t { 
 
     \t \t try 
 
     \t \t { 
 
     \t \t \t File file = new File(fileName); 
 
     \t \t \t channel = new RandomAccessFile(file, "rw").getChannel(); 
 
     \t \t \t lock = channel.lock(); 
 
     \t \t \t 
 
     \t \t \t if(lock != null) 
 
     \t \t \t { 
 
     \t \t \t \t islocked = true; 
 
     \t \t \t \t fileWriter = new FileWriter(fileName); 
 
     \t \t \t \t Gson gson2 = new GsonBuilder().setPrettyPrinting().create(); 
 
         String json2 = gson2.toJson(ObjToWrite); 
 
         fileWriter.write(json2); 
 
     \t \t \t \t writeFlag = true;   \t \t \t \t 
 
     \t \t \t } 
 
     \t \t } 
 
     \t \t catch(OverlappingFileLockException e) 
 
     \t \t { 
 
     \t \t \t logger.error("FILE LOCK OVERLAP EXP OCCURED IN WRITING FILE " + fileName 
 
     \t \t \t \t \t \t \t +". ATTEMPTING TO WRITE FILE AGAIN."); 
 
     \t \t \t 
 
     \t \t \t //release the lock 
 
     \t \t \t if(lock != null) 
 
     \t \t \t { 
 
     \t \t \t \t lock.release(); 
 
     \t \t \t } 
 
     \t \t \t // close the channel 
 
     \t \t \t if(channel != null) 
 
     \t \t \t { 
 
     \t \t \t \t channel.close(); 
 
     \t \t \t } 
 
     \t \t \t synchronized (JsonReader.relock) { 
 
     \t \t \t \t JsonReader.relock.wait(); 
 
\t  \t \t \t } 
 
     \t \t } 
 
     \t } 
 
     } 
 
     catch (FileNotFoundException e) 
 
     { 
 
     \t 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) 
 
     { 
 
     \t e.printStackTrace(); 
 
     \t logger.error("ERROR IN JSON FOR FILE NAMED "+fileName+".",e);   
 
     } 
 
     finally { 
 
      try { 
 
       if(fileWriter != null) 
 
       { 
 
       \t fileWriter.flush(); 
 
       \t fileWriter.close(); 
 
       } 
 
       // release the lock 
 
       if(lock != null) 
 
        lock.release(); 
 
       // close the channel 
 
       if(channel != null) 
 
       { 
 
       \t 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 { 
 
      \t synchronized (JsonReader.relock) { 
 
      \t \t JsonReader.relock.notify(); 
 
    \t \t \t } 
 
\t \t \t } 
 
     }  
 
     return writeFlag; 
 
    } 
 
}

回答