在我们的应用程序中,有一段代码不断运行以读取和调整文件。只是为了让您了解正在发生的事情:
public void run() {
try {
while(true) { //Yeah, I know...
Path currentFileName = getNextFile();
String string = readFile(currentFileName);
Files.deleteFile(currentFileName);
string = string.replaceAll("Hello", "Blarg");
writeFile(currentFileName);
}
} catch (Exception e) {
System.err.println("It's all ogre now.");
e.printStackTrace(System.err);
}
}
我们代码中的其他地方有一个方法,它可能(但通常)不在与上述代码相同的线程上运行,我们用它来退出应用程序。
private void shutdown() {
if(fileReader != null)
fileReader = null;
System.exit(0); //Don't blame me, I didn't write this code
}
很明显,此代码中存在潜在的竞争条件,如果在shutdown()检索文件和写回文件之间调用 if ,则可能会导致文件完全丢失。显然,这是不受欢迎的行为。
这段代码有上千个问题(超出了我在这里展示的范围),但我需要解决的主要问题是处理文件可以中途中断而没有追索权的不良行为。我提出的解决方案涉及简单地将 while 循环包装在一个块中,并在调用synchronized周围放置一个块。System.exitshutdown
所以我更改后的代码如下所示:
private Object monitor = new Object();
public void run() {
try {
while(true) {
synchronized(monitor) {
Path currentFileName = getNextFile();
String string = readFile(currentFileName);
Files.deleteFile(currentFileName);
string = string.replaceAll("Hello", "Blarg");
writeFile(currentFileName);
}
}
} catch (Exception e) {
System.err.println("It's all ogre now.");
e.printStackTrace(System.err);
}
}
private void shutdown() {
synchronized(monitor) {
if(fileReader != null)
fileReader = null;
System.exit(0);
}
}
我主要担心的是System.exit(0);电话,我不确定电话幕后的总体行为。System.exit是否存在将释放锁的副作用的风险monitor,从而导致循环内容在导致 JVM 停止run之前被部分执行的风险?System.exit还是这段代码会保证执行过程永远不会在处理单个文件时尝试中途关闭?
注意:在一些纸上谈兵的程序员介入替代方案之前,我想指出,我在这里放置的是大约 4000 行代码的截断版本,所有代码都隐藏在一个类中。是的,这太可怕了。是的,这让我后悔我选择的职业。我不是在这里寻找这个问题的替代解决方案,我只是想确定这个特定的解决方案是否有效,或者是否存在一些严重的缺陷会阻止它像我预期的那样工作。
PIPIONE
翻阅古今
慕无忌1623718
繁星淼淼
相关分类