每次在我的网站上请求页面时,我都会通过以下服务电话记录一些详细信息:
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分钟安排一次),我会执行另一项重命名此文件并开始处理的服务。
我想了解如何确保并发写入是安全的,并且在写入过程中不执行重命名。我想答案将是某种形式的同步。
答案 0 :(得分:2)
这两个服务需要共享一个同步对象:它可以是任何东西(甚至new byte[1]
)但它必须是同一个实例,并传递到您的“服务”中。只要有关键部分,这意味着代码的一部分想要在共享资源上运行,就需要将其包装在
synchronized(theInstanceOfSynchronizationObject) {
// ... your code for critical section
}
良好锁定的规则是确定性地知道你锁定了什么,什么是共享资源。什么会杀死你(并引入死锁)是随机添加同步块,希望“解决”。在您的特定示例中,最有可能是file
上的操作:只是操作,而不是对文件名字符串的操作,File
的实例化:您可以有很多{{} 1}}指向磁盘上相同文件的对象,并且它不是关键操作,只要它还没有触及磁盘。所以我会说
File
同样,保护其他服务中的File file=new File(filePath);
synchronized(theInstanceOfSynchronizationObject) {
if(file.exists()) {
} else {
}
}
操作。请记住,它不是您要保护的File
对象,而是文件本身。