0

我一直认为并发线程写入同一个文件需要同步。

当多线程在没有同步的情况下将相同的东西写入同一个文件时会发生什么?我想输出文件一定是不完整或损坏的。

public class Test 
{   
  public Runnable createLayoutRunnable() {
    return new Runnable() {
        public void run() {
            try {
                FileInputStream inputStream = new FileInputStream("mov.mp4");

                FileOutputStream outputStream = new FileOutputStream("mov_co.mp4");
                //IOUtils.copy(inputStream, outputStream);

                //synchronized ("lock"){
                int read = 0;
                byte[] bytes = new byte[1024];

                while ((read = inputStream.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, read);
                }
                //}

                System.out.println(Thread.currentThread().getName() + " is done"); 



            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
}


public static void main(String[] args) {
    Test test = new Test();
    //Create Thread Pool for parallel layout
    ExecutorService executor = Executors.newFixedThreadPool(9);

    //Run Tasks and wait for termination in the current thread
    Future<?> f1 = executor.submit(test.createLayoutRunnable());
    Future<?> f2 = executor.submit(test.createLayoutRunnable());
    Future<?> f3 = executor.submit(test.createLayoutRunnable());
    Future<?> f4 = executor.submit(test.createLayoutRunnable());
    Future<?> f5 = executor.submit(test.createLayoutRunnable());
    Future<?> f6 = executor.submit(test.createLayoutRunnable());
    Future<?> f7 = executor.submit(test.createLayoutRunnable());
    Future<?> f8 = executor.submit(test.createLayoutRunnable());
    Future<?> f9 = executor.submit(test.createLayoutRunnable());


    try {
        f1.get();
        f2.get();
        f3.get();
        f4.get();
        f5.get();
        f6.get();
        f7.get();
        f8.get();
        f9.get();


    } catch (Exception ex) {
        ex.printStackTrace();
    }
    executor.shutdown();

    System.out.println("all done");

}

}

惊喜!输出mov很好玩!怎么来的?请帮忙!

编辑:首先,我对混乱感到非常抱歉。是的,我发布的第一次代码是同步的,而不是我所说的。我现在已经评论了。这是因为我在玩代码,这就是我发现它是否同步无关紧要的地方,我想知道为什么。

4

3 回答 3

3

在这种特殊情况下,您将输入文件中的相同内容写入输出文件中的相同位置。这就是所谓的幂等操作,同步与否都无所谓。

如果每个线程都编写了自己的源文件(并且您消除了同步),您会看到(1)一个线程会获胜,或者(2,更有可能)您会得到交错(损坏)的内容。

于 2013-05-23T15:25:55.410 回答
2

多线程访问并不意味着你会得到垃圾。这意味着结果是不可预测的。有些系统可能只是自己同步某些东西,结果可能看起来像是在互斥锁下访问的。

其次,您的代码是同步的,而不是您所说的。您看到同步(“锁定”)部分吗?一开始你说它不同步。然后,我们查看代码并看到它是同步的。然后我们认为第一个线程可见的“锁”与另一个线程看到的不同。但它是同一个对象,因为在 java 中“静态字符串”==“静态字符串”。因此,线程使完整副本处于锁定状态。然后另一个来制作完整的副本。当然,播放将不会中断。

文件操作中唯一超出同步的是文件打开/关闭。(关闭?)在 Linux 中尝试。这可能会产生很大的不同。

于 2013-05-23T15:40:28.140 回答
2

在您的示例中,即使您取消了同步,每个线程也会将相同的内容写入同一个文件。因为每个线程都使用单独的 OutputStream(和 InputStream),所以线程不会干扰彼此的文件位置。因此,输出是输入文件的副本。

这类似于:

public static int a;
public static int b;
public static int c;

线程代码为:

a = 1;
b = 2;
c = 3;

假设您有两个线程,A 和 B。执行顺序可能如下运行,例如:

  • A 设置 a = 1;
  • A 设置 b = 2;
  • B 设置 a = 1;
  • A 设置 c = 3;
  • B 设置 b = 2;
  • B 设置 c = 3;

不管有多少线程运行该序列,也不管它们是否同步,一旦它们完成,{a,b,c} 的内容将始终为 {1,2,3}(有一些不适用的警告写入外部文件时)。这与您复制文件的示例相同 - 输出文件的内容始终相同;线程中的确切执行顺序无关紧要。

于 2013-05-23T15:25:24.463 回答