【发布时间】:2017-01-17 22:02:49
【问题描述】:
我最近使用了 Apache Commons-IO 的类 CountingInputStream。它只是通过更新计数器字段来跟踪读取了多少字节。
我注意到它使用synchronized 关键字更新其计数器。我能找到的最佳来源是IO-201,但它没有解释原因。
我在一些地方读到 Apache Commons 代码质量很好,但我现在想知道为什么它们在 InputStream 中有同步方法。我不认为线程安全是流中有用的属性,IO-201 的评论者也不认为。
鉴于我没有同时访问 InputStream,是否有任何正当理由同步其方法?或者是否有一个有效的用例来同时访问不会产生数据垃圾的 InputStream?
【问题讨论】:
-
我无法理解如何在不获取数据垃圾的情况下同时读取 InputStream。所以我认为并发不能成为
synchronized的动机。但也许这只是我有限的想象力。我不担心,我只是想了解从中学习的动机。 -
好的,我明白了。另一个线程可能会调用
getCount()。如果没有任何同步操作,内存模型就会启动,其他线程可能永远不会看到更新。好的,我很满意。 Volatile 而不是 synchronized 可能也会做同样的工作,对吧? -
不,增加
volatile变量不是线程安全的。 -
多线程并发读取这个流没有意义,
read方法是不同步的。 IMO,使用synchronized的唯一原因是确保计数器的安全发布。volatile在这里还不够,因为我们正在做read-update-write,AtomicLong可能是一个有效的替代方案。 -
假设更新计数器是外部同步的,因为它只发生在流的读取操作期间。因此,它受到外部保护,免受竞争条件的影响。另一个线程可能只读取计数器(getCount() 没有任何更新)。因此 volatile 可能足以作为发生前发生的规则,不是吗?实际上这也是IO-201 的作者所声称的:“如果只有一个线程读取流,那么计数字段可能会变为易失性。这将允许其他线程安全地读取计数。”
标签: java inputstream synchronized apache-commons-io