锁分段技术+写数组的拷贝+旧的线程安全的集合+同步包装器
来源:互联网 发布:收支软件 编辑:程序博客网 时间:2024/05/18 02:40
问题
如下面这段代码:
- // shm是SynchronizedMap的一个实例
- if(shm.containsKey('key')){
- shm.remove(key);
- }
这段代码用于从map中删除一个元素之前判断是否存在这个元素。这里的containsKey和reomve方法都是同步的,但是整段代码却不是。考虑这么一个使用场景:线程A执行了containsKey方法返回true,准备执行remove操作;这时另一个线程B开始执行,同样执行了containsKey方法返回true,并接着执行了remove操作;然后线程A接着执行remove操作时发现此时已经没有这个元素了。要保证这段代码按我们的意愿工作,一个办法就是对这段代码进行同步控制,但是这么做付出的代价太大。
在进行迭代时这个问题更改明显。Map集合共提供了三种方式来分别返回键、值、键值对的集合:
Set<K> keySet();Collection<V> values();Set<Map.Entry<K,V>> entrySet();
在这三个方法的基础上,我们一般通过如下方式访问Map的元素:
Iterator keys = map.keySet().iterator();while(keys.hasNext()){ map.get(keys.next());}
在这里,有一个地方需要注意的是:得到的keySet和迭代器都是Map中元素的一个“视图”,而不是“副本”。
问题也就出现在这里,当一个线程正在迭代Map中的元素时,另一个线程可能正在修改其中的元素。此时,在迭代元素时就可能会抛出ConcurrentModificationException异常。
为了解决这个问题通常有两种方法:
一种方法(方法一)是直接返回元素的副本,而不是视图。这个可以通过
集合类的 toArray()方法实现,但是创建副本的方式效率比之前有所降低,特别是在元素很多的情况下;
另一种方法(方法二)就是在迭代的时候锁住整个集合,这样的话效率就更低了。
旧的线程安全集合(方法二)
效率低下的HashTable容器
HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下HashTable的效率非常低下。因为当一个线程访问HashTable的同步方法时,其他线程访问HashTable的同步方法时,可能会进入阻塞或轮询状态。如线程1使用put进行添加元素,线程2不但不能使用put方法添加元素,并且也不能使用get方法来获取元素,所以竞争越激烈效率越低。
为了解决这个问题 ,提出了同步包装器
同步包装器
static
<T> Collection<T>
synchronizedCollection(Collection<T> c)
返回指定 collection 支持的同步(线程安全的)collection。
static
<T> List<T>
synchronizedList(List<T> list)
返回指定列表支持的同步(线程安全的)列表。
static
<K,V> Map<K,V>
synchronizedMap(Map<K,V> m)
返回由指定映射支持的同步(线程安全的)映射。
static
<T> Set<T>
synchronizedSet(Set<T> s)
返回指定 set 支持的同步(线程安全的)set。同步包装器在使用迭代器时必须使用客户端封锁:
// shm是SynchronizedMap的一个实例if(shm.containsKey('key')){ shm.remove(key);}
这段代码用于从map中删除一个元素之前判断是否存在这个元素。这里的containsKey和reomve方法都是同步的,但是整段代码却不是。考虑这么一个使用场景:线程A执行了containsKey方法返回true,准备执行remove操作;这时另一个线程B开始执行,同样执行了containsKey方法返回true,并接着执行了remove操作;然后线程A接着执行remove操作时发现此时已经没有这个元素了。
注意:foreach也使用了迭代器所以也要使用客户端封锁写数组的拷贝(方法一)
锁分段技术
- 锁分段技术+写数组的拷贝+旧的线程安全的集合+同步包装器
- Java知识点整理:第十章:包装类、集合的复制、集合线程同步化(线程安全)、集合与数组的相互转换
- 集合的同步包装器类
- 包装线程不安全的集合
- 安全的线程同步
- 安全的线程同步
- 安全的线程同步
- 安全的线程同步
- 安全的线程同步
- 安全的线程同步
- 线程安全的集合
- 线程安全的集合
- Java集合框架官方教程(5):集合类的同步包装器/不可变包装器
- java同步包装器与线程安全
- 集合类 :VBA集合对象的安全包装
- 集合类:VBA集合对象的安全包装
- 线程的同步-集合的同步
- 线程安全的集合类
- 《unix高级环境编程》进程环境——进程资源限制
- Quartz 入门详解
- Nodejs学习路线图
- 多线程时使用shared_from_this的一个注意问题
- 第13周项目5-字符串操作(2.1)
- 锁分段技术+写数组的拷贝+旧的线程安全的集合+同步包装器
- 《unix高级环境编程》进程控制——进程ID
- ORACLE文件误删除的回复
- 移动端尺寸基础知识
- 详解KDTree
- Core Data 介绍
- 朴素贝叶斯算法Java实现
- 《unix高级环境编程》进程控制——创建进程
- 揭秘响一声电话吸费 声讯电话平台