【问题标题】:Latency in file creation when file is created by a thread and read by another thread文件由一个线程创建并由另一个线程读取时的文件创建延迟
【发布时间】:2021-10-06 16:14:05
【问题描述】:

主要代码

我有一种方法使用服务来推送作业并等待此类服务在某处创建文件。

这样的服务公开了两种方法:

  • String pushJob(...)
  • boolean isJobReady(String id) true,否则返回false

为了等待,这个方法做了这样的事情:

CompletableFuture<Void> waiter = new CompletableFuture<>();
waitFor(waiter, jobId); //<-- this will poll on the isJobReady endpoint until it responds with true
                        //    when this happens, it will complete the future.
waiter.get(1, TimeUnit.HOUR); //<-- wait for the job to complete within the hour
//do something with the file that was created once the get returns without exceptions

单元测试

这很好用,但我想测试一下。因此,我做了一个服务的模拟实现,公开了pushJobisJobReady 两种方法:

public class MockService implements Service {

    private volatile boolean isReady;

    @Override
    public String pushJob() {
        isReady = false;
        CompletableFuture.runAsync(() -> {
            Thread.sleep(10000); //<-- simulates the time spent to perform the job on service side
            File file = new File("..."); 
            if (file.createNewFile()) {
                isReady = true;
            } else {
                throw new IllegalStateException("Could not create test file");
            }
        });
        return "12345";
    }

    @Override
    public boolean isJobReady(String id) {
        return isReady;
    }
}

然后我在我的代码中注入这样的模拟实现以对其进行测试。

问题

mock 实现创建文件后,将 volatile 字段 isReady 设置为 true,因此当主代码看到它时,它会立即去搜索创建的文件。

但是,它会在两次中找到一次。

如果我在搜索文件之前设置断点并等待一秒钟,代码将系统地成功。 但是,如果我以正常的执行速度(或简单的编译时间)进行测试,测试就会变得非常不稳定。

我发现这是一个多线程问题,但我真的不明白这是怎么可能的,因为测试代码不会设置变量 isReady = true,直到它得到来自 createNewFile() 的响应(根据到javadoc)Atomically creates a new, empty file named by this abstract pathname if and only if a file with this name does not yet exist.

为什么会发生这种情况?如何正确同步文件系统,以便在模拟服务中创建文件在主代码上正确可见?

【问题讨论】:

    标签: java multithreading file concurrency


    【解决方案1】:

    依赖文件系统的一般方式似乎是错误的。我不认为您可以期望新文件立即对所有人和所有人都可见。

    我会扩展方法isJobReady。它还必须确保该文件确实存在并且对工作线程可见。方法 isJobReady 必须返回 false 否则(如果情况与 RAM 状态不同步,可能会将警告写入日志)。

    更新:这是一个类似的问题,只有一个线程。原子性不属于文件系统的强项:Creating new files concurrently

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-14
      • 1970-01-01
      • 1970-01-01
      • 2018-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多