同步容器,并发容器(java并发编程实践读书笔记一)
java并发编程实践中摘录的重点-绿色文字为jdk文档中复制的同步容器 同步容器类包括两部分 1.vector 和 hashtable (早起jdk的一部分) 2.Collections.synchronizedXXX工厂方法创建的(jdk1.2中才加入的) 同步容器都是线程安全的,但是对于复合操作,需要额外的
·
java并发编程实践中摘录的重点-绿色文字为jdk文档中复制的
同步容器
同步容器类包括两部分
1.vector 和 hashtable (早起jdk的一部分)
2.Collections.synchronizedXXX工厂方法创建的(jdk1.2中才加入的)
同步容器都是线程安全的,但是对于复合操作,需要额外的客户端加锁(jdk文档中有明确的说明)。
复合操作:
迭代iterate
导航navigation
条件运算 (比如:list操作,缺少即加入--先检查list中是否存在,不存在则加入)
以下内容复制自jdk6.0文档
synchronizedList
public static <T> List<T> synchronizedList(List<T> list)
-
返回指定列表支持的同步(线程安全的)列表。为了保证按顺序访问,必须通过返回的列表完成所有对底层实现列表的访问。
在返回的列表上进行迭代时,用户必须手工在返回的列表上进行同步:
List list = Collections.synchronizedList(new ArrayList()); ... synchronized(list) { Iterator i = list.iterator(); // Must be in synchronized block while (i.hasNext()) foo(i.next()); }
不遵从此建议将导致无法确定的行为。
由 Vector 的 iterator 和 listIterator 方法所返回的迭代器是快速失败(fail-fast )的:如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代器自身的 remove 或 add 方法之外的任何其他方式),则迭代器将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生不确定行为的风险。Vector 的 elements 方法返回的 Enumeration 不是 快速失败的。
注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出ConcurrentModificationException
。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测 bug。
通过在迭代期间持有同步容器的锁,防止其他线程在迭代期间修改该容器(例如:迭代时其他线程remove元素,造成迭代时抛出ConcurrentModificationException,使用for each迭代时也会出现这种情况)
隐性迭代
toString,hashCode,equalse,containsAll,removeAll,retainAll等方法都会隐式的Iterate,可能抛出ConcurrentModificationException
同步容器通过对容器所有状态(容器中的所有元素)进行串行访问,从而实现线程安全,代价是削弱了并发性
同步容器仅仅是全部的方法使用synchronized修饰了,一个公共锁同步每一个方法,并严格的限制了只能一个线程同时访问容器。
并发容器(jdk5.0新增的)
concurrentHashMap
使用更加细化的锁机制 --
分离锁(允许更深层次的共享访问,为并发带来更高的吞吐量)
任意数量的读线程可以并发的访问map;读,写线程可以并发访问;允许并发修改map
提供的迭代器具有 弱一致性(非 快速失败的)迭代器允许并发修改。迭代器被设计成每次仅由一个线程使用(
单一线程迭代)。
提供了常见复合操作,以原子方式执行的
putIfAbsent
public V putIfAbsent(K key, V value)
-
如果指定键已经不再与某个值相关联,则将它与给定值关联。这等价于:
if (!map.containsKey(key)) return map.put(key, value); else return map.get(key);
public boolean replace(K key, V oldValue, V newValue)
-
只有目前将键的条目映射到给定值时,才替换该键的条目。这等效于:
if (map.containsKey(key) && map.get(key).equals(oldValue)) { map.put(key, newValue); return true; } else return false;
remove
public boolean remove(Object key, Object value)
-
只有目前将键的条目映射到给定值时,才移除该键的条目。这等效于:
if (map.containsKey(key) && map.get(key).equals(value)) { map.remove(key); return true; } else return false;
-
其他方法请参阅jdk文档
CopyOnWriteArrayList
同步list的一个并发代替品
写入时复制--
理论依据 只要有效的不可变对象被正确的发布,访问它将不再需要更多的同步 ???
修改时 创建并重新发布一个新的容器拷贝,以此来实现可变性???
允许多线程迭代访问,迭代器返回的元素严格与迭代器创建时一致,不会考虑后续的修改~
对容器的迭代操作远远高于对容器的修改操作频率时使用 -- 修改时拷贝需要一定的开销
与之类似的还有
CopyOnWriteArraySet(同步set的并发替代品)
大多数情况下可以用
并发容器取代
同步容器
更多推荐
已为社区贡献1条内容
所有评论(0)