gpt4 book ai didi

多线程和多进程的Java文件锁定方式

转载 作者:行者123 更新时间:2023-12-03 23:13:41 58 4
gpt4 key购买 nike

我有超过 3 个 java 进程访问相同的文件进行读写。每个进程都有多个线程,它们非常频繁地读写文件(以 1 秒内 10 次左右的速度)。

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

我在这个实现中面临的问题是 -

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

  • 我的问题是,
  • 如果线程在读取或写入完成后立即释放文件锁,那么为什么会出现问题 1?
  • 如果文件在读取之前被所有进程的每个线程锁定,或者
    写那么为什么会出现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 {

    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 操作系统很可能无法识别 2 个不同的线程在同一个 JVM 中运行。
    参见 https://gist.github.com/harrah/4714661 中的类似示例这里。

    关于多线程和多进程的Java文件锁定方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37695060/

    58 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com