[当多个线程尝试在JAVA中使用NIO附加内容时是否需要锁定文件?

问题描述 投票:1回答:2

[首先,我创建了一个空文件。然后,我启动一些线程来搜索数据库并获取结果内容,然后追加到文件中。结果内容为String类型,可能为20M,但是每个线程一次写入一次文件。我已经测试了很多次,发现没有必要进行锁定。对吗?示例的总行数为1000。何时应该添加写锁定来操作文件?

    String currentName = "test.txt";
    final String LINE_SEPARATOR = System.getProperty("line.separator");
    ThreadPoolExecutor pool = new ThreadPoolExecutor(
            10, 100, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
    for (int i = 0; i < 500; i++) {
        pool.execute(() -> {
            try {
                appendFileByFilesWrite(currentName, "abc" +
                        ThreadLocalRandom.current().nextInt(1000) + LINE_SEPARATOR);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    IntStream.range(0, 500).<Runnable>mapToObj(a -> () -> {
        try {
            appendFileByFilesWrite( currentName,
                    "def" +
                            ThreadLocalRandom.current().nextInt(1000) + LINE_SEPARATOR);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }).forEach(pool::execute);

    pool.shutdown(); 

这里是方法:

public static void appendFileByFilesWrite(String fileName,String fileContent) throws IOException {
    Files.write(Paths.get(fileName), fileContent.getBytes(),StandardOpenOption.APPEND);
}
java multithreading java-8 java.util.concurrent threadpoolexecutor
2个回答
1
投票

答案是:总是

您的测试对您有效。马上。今天。也许在满月期间不会。也许如果您购买一台新计算机,或者您的OS供应商更新,或者是JDK更新,或者您正在Winamp中播放布兰妮斯皮尔斯之歌,就不会。

该规范说,在多个步骤上拖尾写入是合法的,并且SOO.APPEND的行为当时未定义。如果同时写入“ Hello”和“ World”,则文件可能最终包含“ HelWorllod”。可能不会。但是可以。

通常,并发性错误很难测试(有时实际上是不可能的)。至少不会造成错误;大多数情况下,您会收到大量的错误报告,并且对所有错误报告都回答“无法重现”。这不是一个好地方。

[如果您想观察实际问题,很可能应该在编写器中写非常长的字符串;目的是最终得到涉及多个分离块的实际低级磁盘命令。即使这样,也无法保证您会发现问题。但是,没有证据不是没有证据。


0
投票

[我们知道Java NIO支持并发和多线程,这使它能够同时处理在多个文件上运行的多个线程。但是在某些情况下,我们要求我们的文件不能被任何线程共享并且不能被非线程共享。无障碍。

所以我认为YES,锁定文件可以使我们免于许多潜在的错误。

出于这种要求,NIO再次提供了一个称为FileLock的API,该API用于提供对整个文件或文件的一部分的锁定,以使文件或其部分不会共享或不可访问。

© www.soinside.com 2019 - 2024. All rights reserved.