1

每次在我的网站上请求一个页面时,我都会通过如下服务调用记录一些详细信息:

logService.logPageRequest(session, request, contentId);

此服务调用使用静态 FileUtils(我自己的)方法对文件进行实际更新。

public static void appendToTextFile(String string, String fileRootDirectory, String subdirectory, String filename, boolean startOnNewLine) throws Exception {
    // code irrelevant to the question removed

    String filePath=fileDirectory+"/"+filename;
    File file=new File(filePath);
    if(file.exists()) {
        FileWriter out = new FileWriter(filePath, true);
        if(startOnNewLine) {
            out.write("\r\n");
        }
        out.write(string);
        out.close();
     } else {
         FileWriter out = new FileWriter(filePath);
         out.write(string);
         out.close();
}

每隔一段时间(假设每 15 分钟安排一次),我执行另一个服务,该服务重命名此文件并开始处理它。

我想了解如何确保两个并发写入都是安全的,并且在写入过程中不执行重命名。我想答案将是某种形式的同步。

4

1 回答 1

2

这两个服务需要共享一个同步对象:它可以是任何东西(甚至new byte[1]),但它必须是同一个实例,传递到您的“服务”中。每当有一个临界区,这意味着代码的一部分想要对共享资源进行操作时,就需要将它包装起来。

synchronized(theInstanceOfSynchronizationObject) {
  // ... your code for critical section
}

良好锁定的规则是确定性地知道您要锁定什么,共享资源到底是什么。什么会杀死你(并引入死锁)是随机添加同步块以希望“解决”。在您的特定示例中,很可能是对file:的操作,而不是对文件名字符串的操作,也不是对File: 的实例化,您可以有许多File对象指向磁盘上的同一个文件,这不是关键操作,只要它还没有接触到磁盘。所以我会说

File file=new File(filePath);
synchronized(theInstanceOfSynchronizationObject) {
  if(file.exists()) {
  } else {
  }
}

同样,保护您的其他服务中的File 操作。请记住,File您要保护的不是对象,而是文件本身

于 2012-11-19T09:44:25.447 回答