【问题标题】:Why are the write(..) methods java.io.Writer synchronized?为什么 java.io.Writer 的 write(..) 方法是同步的?
【发布时间】:2016-06-09 19:06:00
【问题描述】:

我正在使用 java.io.FileWriter 将一些数据写入磁盘。 如您所知,FileWriter 扩展了 OutputStreamWriter,而后者又扩展了 Writer。

当我查看 Writer 的 write(..) 时,令我惊讶的是它是同步的。

**java.io.Writer**

    public void write(int c) throws IOException {
        synchronized (lock) {
            if (writeBuffer == null){
                writeBuffer = new char[WRITE_BUFFER_SIZE];
            }
            writeBuffer[0] = (char) c;
            write(writeBuffer, 0, 1);
        }
    }

我很好奇为什么写入在基 Writer 类中是同步的? 对于我的用例,我只有一个编写器线程,并且绝对不需要同步 writes(..)。

我知道获取非竞争锁比竞争锁快得多。然而,对我来说,同步 Writer 基类的整个业务看起来并不是一个好的设计。

我错过了一个未同步的 Writer 类吗?

谢谢

【问题讨论】:

  • 我可以理解这种惊讶,但如果你有一个单一的作家线程,那么它在实践中并没有太大的区别,不是吗?我的问题是,您是出于好奇,还是试图实现我可能错过的某个特定目标?
  • 由于 Java 6 应用了escape analysis,因此不会获取永远无法争用的锁。因此,它在源代码中同步通常不会有什么坏处,并且可能会避免在其他情况下您没有预料到的并发错误。
  • 对于使用多线程的人来说,这是非常必要的。对于不使用多线程的人来说,由于无竞争锁占用的时间比写入本身要少很多(I/O 一般要慢一个数量级),所以可以忽略不计。

标签: java multithreading file-io io filewriter


【解决方案1】:

我很好奇为什么写入在基 Writer 类中同步?

无论您是否需要线程安全,此实现都将正常工作。这意味着它将适用于最广泛的用例。

对于我的用例,我只有一个写入线程,完全不需要同步 writes(..)。

如果您每次只使用同一个线程锁定一个对象,它会非常有效地执行此操作(如果您启用了默认的偏向锁定)

我错过了一个未同步的 Writer 类吗?

它的开销非常小,您可以在 CPU 密集型任务中测量,但它大约是实际写入 IO 延迟的 1/1000。即,您将无法区分您的用例。

【讨论】:

  • 嗨,彼得,感谢您的 cmets。我会让 Writer 保持未同步状态,并在其上添加一个同步版本并让用户选择。我同意快速获取非竞争锁,但情况并非总是如此,而且它永远不会比非同步版本更快(如果他们有的话)。
猜你喜欢
  • 2011-08-22
  • 2019-06-05
  • 2012-12-27
  • 2018-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-29
  • 2017-05-05
相关资源
最近更新 更多