同步InputStream有什么好处?

时间:2017-01-17 22:02:50

标签: java inputstream synchronized apache-commons-io

我最近使用过Apache Commons-IO的类CountingInputStream。它只是通过更新计数器字段来跟踪读取的字节数。

我注意到它使用synchronized关键字更新了其计数器。我能找到的最好的来源是IO-201,但它没有解释原因。

我在一些地方读到Apache Commons代码质量很好,但我现在想知道为什么他们在InputStream中有同步方法。我不认为线程安全是流上的有用属性,也不认为IO-201的评论员。

鉴于我没有同时访问InputStream,是否有任何有效理由使其方法同步?或者是否有一个有效的用例来同时访问一个不会产生数据垃圾的InputStream?

1 个答案:

答案 0 :(得分:4)

  

鉴于我没有同时访问public class PartyMaker { private readonly SemaphoreSlim _slowStuffSemaphore = new SemaphoreSlim(1, 1); private readonly ConcurrentDictionary<int, int> _requestCounts = new ConcurrentDictionary<int, int>(); private readonly ConcurrentDictionary<int, DateTime> _cache = new ConcurrentDictionary<int, DateTime>(); public async Task<DateTime> ShakeItAsync(Argument argument) { var key = argument.GetHashCode(); DateTime result; try { if (!_requestCounts.ContainsKey(key)) { _requestCounts[key] = 1; } else { ++_requestCounts[key]; } var needNewRequest = _requestCounts[key] == 1; await _slowStuffSemaphore.WaitAsync().ConfigureAwait(false); if (!needNewRequest) { _cache.TryGetValue(key, out result); return result; } _cache.TryAdd(key, default(DateTime)); result = await ShakeItSlowlyAsync().ConfigureAwait(false); _cache[key] = result; return result; } finally { _requestCounts[key]--; if (_requestCounts[key] == 0) { int temp; _requestCounts.TryRemove(key, out temp); _cache.TryRemove(key, out result); } _slowStuffSemaphore.Release(); } } private async Task<DateTime> ShakeItSlowlyAsync() { await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false); return DateTime.UtcNow; } } public class Argument { public Argument(int value) { Value = value; } public int Value { get; } public override int GetHashCode() { return Value.GetHashCode(); } } ,是否有任何正当理由使其方法同步?

不,没有正当理由让您对仅从单个线程访问的对象使用同步方法。话虽这么说,你正在使用同步的第三方代码来保护可变状态(InputStream字段),所以除了自己实现它之外你没有太多选择。

  

或者是否有一个有效的用例同时访问count不会产生数据垃圾?

InputStream?可能不是。一个InputStream?当然......在一个线程中,我反复调用CountingInputStream来使用流,而在另一个线程中,我反复调用CountingInputStream.read()来更新我的UI以显示我读过的行数。