【发布时间】:2014-08-28 11:55:45
【问题描述】:
为了一个简单的目的,我创建了一个小型 Java servlet:一旦调用它,它将执行以下步骤:
- 从本地文件系统读取文件 foo.json
- 处理文件中的数据并对其进行一些更改
- 将更改写回文件
简化版代码:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
FileInputStream inputStream = new FileInputStream("foo.json");
String filecontent = IOUtils.toString(inputStream);
inputStream.close();
JSONObject json = new JSONObject(filecontent);
doSomeChangesTo(json);
FileWriter writer = new FileWriter("foo.json");
writer.write(json.toJSONString());
writer.flush();
writer.close();
}
现在我面临这样一个问题,即 servlet 几乎同时被两个或多个对 servlet 的 http 请求调用。为了避免对同一个文件的多个并行写访问,我需要以某种方式同步它。根据我对 servlet 生命周期过程的理解,每个请求都会产生一个新线程,因此使用 FileLock 可能不会有任何影响:
代表整个 Java 虚拟机持有文件锁。他们 不适合控制多线程对文件的访问 在同一个虚拟机中。
(来自http://docs.oracle.com/javase/7/docs/api/java/nio/channels/FileLock.html)
我猜想使用 synchronized(){} 关键字也行不通,因为我想同步文件系统访问而不是访问变量/对象。
那么,当 servlet 上发生多个并行请求时,如何在我的 servlet 中同步文件系统访问?
【问题讨论】:
-
在处理文件时重命名文件?我想使用数据库而不是文件不是您的决定吗?
-
如果您的应用程序是唯一一个写入文件的应用程序(并且不是集群),则同步可以正常工作。人们通常使用为您处理并发访问的数据库。
-
您想究竟在此处同步什么?是读-写-写的整个过程吗?或者是个人读写,而处理可以交织在一起(并且您可以从旧读取中写回数据)?
-
@Fildor 正确,目前没有选择使用数据库
-
@JBNizet 所以我只需将我发布的代码包装成
synchronized(){}就可以了?
标签: java file concurrency synchronized filelock