具有恒定大小操作的线程安全NavigableSet?

时间:2012-08-23 12:46:42

标签: java multithreading data-structures collections thread-safety

我正在搜索一个与ConcurrentSkipListSet完全相同但没有线性size - 操作的特定数据结构,对于较大的集合,这种结构可能经常被调用。

我知道Collections.synchronizedNavigableSet(new TreeSet()),但同步迭代:

synchronized (set) {
    Iterator<T> iter = set.iterator();
    while (iter.hasNext())
    iter.next();
}

很慢。

那么,您是否了解NavigableSet实现与ConcurrentSkipListSet完全相同但没有线性size操作,例如Apache Commons,Guava?或者我应该在集合上进行不同的迭代?

1 个答案:

答案 0 :(得分:3)

有充分的理由说明他们没有这样做(即与柜台一起)。 它是关于多处理器编程的语义。 并发程序有许多正确性模型,强 - 称为顺序一致性和放松 - 称为静态一致性(参见Maurice Herlihy和Nir Shavit的多处理器编程艺术或Quasi-Linearizability)。

计数器的实施无法遵守其中任何一项。 如果在实际的添加和删除操作之前更新了大小,它可能会变为负数(假设您已删除并添加空集,请先删除更新的大小,从而导致-1大小...)。如果之后更新尺寸也是如此。 甚至在添加操作之前增加尺寸并在移除之后减小尺寸的解决方案也具有严重的缺点(但是不会产生负值)。考虑两个带参数'x'的add操作和一个带有相同参数'x'的remove(全部具有相同的元素)。可能存在这样的情况:大小将被设置为2(两个添加操作增加了计数器),一个从未存在的状态(该组的大小从未超过2,注意我们总是添加相同的元素'x'和该集不能包含重复项。)

它的实现方式(通过计算具有线性时间复杂度的元素)将至少产生一个在某个时间点存在的值(更确切地说,它是静态一致的)。