Util 创建在指定互斥量上同步的列表
Util creating a list synchronized on a specified mutex
是否有一些实用程序可以创建在指定互斥量上同步的列表?喜欢 java.util.Collections.synchronizedList(List<T> list, Object mutex)
但 public?
没有这样的 public
方法可以让您控制同步集合将使用的互斥量。因此,如果它不是允许您指定互斥量的列表,则必须以这种灵活性实现更高级别的操作,例如:
public static <T> boolean addIfNew(List<T> target, T value, Object mutex) {
synchronized (mutex) {
return !target.contains(value) && target.add(value);
}
}
然后可以用作
List<String> synchedList=Collections.synchronizedList(new ArrayList<String>());
addIfNew(synchedList, "foo", synchedList);
这是有效的,因为 synchronizedList
返回的列表将使用自身作为互斥体。与 its documentation 比较:
强调我的
It is imperative that the user manually synchronize on the returned list when iterating over it:
List list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
实现允许在内部使用不同的互斥对象的原因是您可以创建 sub lists 并且同步列表的子列表将在后备列表实例而不是自身上同步(同样适用于 Vector.subList
).因此,当您将子列表传递给高级方法时,将原始同步列表作为互斥量传递是至关重要的。
类似的事情适用于 Collection
地图视图:
It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views:
Map m = Collections.synchronizedMap(new HashMap());
...
Set s = m.keySet(); // Needn't be in synchronized block
...
synchronized (m) { // Synchronizing on m, not s!
Iterator i = s.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
对此有一个简化。如果您确保对集合的所有访问都发生在您的方法中,那么这些方法可能会同意任意互斥锁,并且如果一致地对该互斥锁进行同步,则它们是线程安全的。当然,集合本身没有必要自己做额外的同步,但这就是它的全部意义所在:
在实践中,您几乎找不到这些同步集合有任何有用的场景。任何重要的操作都需要对集合进行多次访问,因此需要手动或更高级别的同步,这使得低级同步已过时。
考虑将同步集合传递给使用集合的任意方法并自动获得线程安全而无需额外的同步是很诱人的,但是因为只有当所述方法包含对集合的一次访问时才有效,你不会'找不到任何有用的现实生活方法。
所以最重要的是,您将始终必须使您的代码线程安全并控制对集合的访问,因此永远不需要同步集合。
是否有一些实用程序可以创建在指定互斥量上同步的列表?喜欢 java.util.Collections.synchronizedList(List<T> list, Object mutex)
但 public?
没有这样的 public
方法可以让您控制同步集合将使用的互斥量。因此,如果它不是允许您指定互斥量的列表,则必须以这种灵活性实现更高级别的操作,例如:
public static <T> boolean addIfNew(List<T> target, T value, Object mutex) {
synchronized (mutex) {
return !target.contains(value) && target.add(value);
}
}
然后可以用作
List<String> synchedList=Collections.synchronizedList(new ArrayList<String>());
addIfNew(synchedList, "foo", synchedList);
这是有效的,因为 synchronizedList
返回的列表将使用自身作为互斥体。与 its documentation 比较:
强调我的
It is imperative that the user manually synchronize on the returned list when iterating over it:
List list = Collections.synchronizedList(new ArrayList()); ... synchronized (list) { Iterator i = list.iterator(); // Must be in synchronized block while (i.hasNext()) foo(i.next()); }
实现允许在内部使用不同的互斥对象的原因是您可以创建 sub lists 并且同步列表的子列表将在后备列表实例而不是自身上同步(同样适用于 Vector.subList
).因此,当您将子列表传递给高级方法时,将原始同步列表作为互斥量传递是至关重要的。
类似的事情适用于 Collection
地图视图:
It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views:
Map m = Collections.synchronizedMap(new HashMap()); ... Set s = m.keySet(); // Needn't be in synchronized block ... synchronized (m) { // Synchronizing on m, not s! Iterator i = s.iterator(); // Must be in synchronized block while (i.hasNext()) foo(i.next()); }
对此有一个简化。如果您确保对集合的所有访问都发生在您的方法中,那么这些方法可能会同意任意互斥锁,并且如果一致地对该互斥锁进行同步,则它们是线程安全的。当然,集合本身没有必要自己做额外的同步,但这就是它的全部意义所在:
在实践中,您几乎找不到这些同步集合有任何有用的场景。任何重要的操作都需要对集合进行多次访问,因此需要手动或更高级别的同步,这使得低级同步已过时。
考虑将同步集合传递给使用集合的任意方法并自动获得线程安全而无需额外的同步是很诱人的,但是因为只有当所述方法包含对集合的一次访问时才有效,你不会'找不到任何有用的现实生活方法。
所以最重要的是,您将始终必须使您的代码线程安全并控制对集合的访问,因此永远不需要同步集合。