如果不能保证对迭代器的同步访问,我们为什么要使用同步集合?
Why do we use synchronized collection if it doesn't guarantee the synchronized access on iterators?
例如,在下面的代码中,我们必须在进行迭代时将列表包装在同步块中。 Collections.synchronizedList 是否使列表同步?如果它不提供任何便利,我们为什么要这样做?谢谢!
List<Integer> list = Collections.synchronizedList( new ArrayList<>(Arrays.asList(4,3,52)));
synchronized(list) {
for(int data: list)
System.out.print(data+" ");
}
见https://docs.oracle.com/javase/tutorial/collections/implementations/wrapper.html
The reason is that iteration is accomplished via multiple calls into the collection, which must be composed into a single atomic operation.
Wrapper 用于同步添加和删除包装集合中的元素。
JavaDoc 提到迭代不同步,您需要自己同步它。
* It is imperative that the user manually synchronize on the returned
* list when iterating over it
但是其他访问操作是线程安全的并且也建立了happens before关系(因为它们使用synchronized
)。
Why do we do this if it doesn't provide any convenience
它在迭代时没有帮助你不等于没有提供便利。
所有方法 - get
、size
、set
、isEmpty
等 - 都是同步的。这意味着它们可以看到在任何线程中进行的所有写入。
如果没有同步,就无法保证一个线程中所做的更新对任何其他线程都是可见的,因此一个线程可能看到大小为 5 而另一个线程看到大小为 6,例如。
使列表同步的机制是使其所有方法synchronized
:这实际上意味着方法的主体被包裹在synchronized (this) { ... }
块中。
iterator()
方法仍然如此:synchronized
也是如此。但是 synchronized
块在 iterator()
returns 时完成,而不是在您完成迭代时完成。这是语言设计方式的基本限制。
所以你必须自己添加同步块来帮助语言。
Collections.synchronizedList
方法同步 add
、remove
等方法。但是,它不同步 iterator()
方法。考虑以下场景:
- 线程 1 正在遍历列表
- 线程 2 正在向其中添加一个元素
在这种情况下,您将获得 ConcurrentModificationException
,因此,必须同步对 iterator()
方法的调用。
例如,在下面的代码中,我们必须在进行迭代时将列表包装在同步块中。 Collections.synchronizedList 是否使列表同步?如果它不提供任何便利,我们为什么要这样做?谢谢!
List<Integer> list = Collections.synchronizedList( new ArrayList<>(Arrays.asList(4,3,52)));
synchronized(list) {
for(int data: list)
System.out.print(data+" ");
}
见https://docs.oracle.com/javase/tutorial/collections/implementations/wrapper.html
The reason is that iteration is accomplished via multiple calls into the collection, which must be composed into a single atomic operation.
Wrapper 用于同步添加和删除包装集合中的元素。
JavaDoc 提到迭代不同步,您需要自己同步它。
* It is imperative that the user manually synchronize on the returned
* list when iterating over it
但是其他访问操作是线程安全的并且也建立了happens before关系(因为它们使用synchronized
)。
Why do we do this if it doesn't provide any convenience
它在迭代时没有帮助你不等于没有提供便利。
所有方法 - get
、size
、set
、isEmpty
等 - 都是同步的。这意味着它们可以看到在任何线程中进行的所有写入。
如果没有同步,就无法保证一个线程中所做的更新对任何其他线程都是可见的,因此一个线程可能看到大小为 5 而另一个线程看到大小为 6,例如。
使列表同步的机制是使其所有方法synchronized
:这实际上意味着方法的主体被包裹在synchronized (this) { ... }
块中。
iterator()
方法仍然如此:synchronized
也是如此。但是 synchronized
块在 iterator()
returns 时完成,而不是在您完成迭代时完成。这是语言设计方式的基本限制。
所以你必须自己添加同步块来帮助语言。
Collections.synchronizedList
方法同步 add
、remove
等方法。但是,它不同步 iterator()
方法。考虑以下场景:
- 线程 1 正在遍历列表
- 线程 2 正在向其中添加一个元素
在这种情况下,您将获得 ConcurrentModificationException
,因此,必须同步对 iterator()
方法的调用。