java多线程(七) 之 同步容器类
2017-05-18 11:45
218 查看
同步容器类都是线程安全的,但在某些情况下可能需要额外的客户端加锁来保护复合操作,比如如下:
1.线程不安全的复合操作1:
线程B可能获取了list.size()-1的值之后,此时如果线程A执行了list.remove(lastIndex),那么线程B再接着执行return list.get(lastIndex);将会报ArrayIndexOutOfBoundsException异常
2.线程不安全的复合操作2:
如果给方法加上synchronized锁呢?
结论是,线程仍然不安全,理由:
虽然按照上一题的中的线程A,B之间是安全的,但是,如果是下面的情况:
Vector list;
A线程:UnsafeVectorOperation2.getLast(list)
C线程:list.remove(list.size()-1);
所以上面的代码只能限制线程同时调用UnsafeVectorOperation2里的方法安全,一旦有其他线程也调用list,那么上面的代码就傻逼了.
3.如果给list上锁,使得复合操纵变为原子操作.
UnsafeVectorOperation3 当中的确不存在线程不安全的问题了,但是其他线程对list的操作仍然线程不安全,这个不安全可以来自其他线程对UnsafeVectorOperation3的调用,例如:
4.带有客户端锁的迭代,这下安全了,只不过…
在遍历期间,将会导致其他线程对list的访问,数据量越大,迭代越长,并发效率大大降低.很多时候得不偿失.
5.使用迭代器来迭代,解决并发效率低的问题:
至今所有的容器都并没有真正达到”既百分百安全,效率又很高”,而只能采取折中的方案.
迭代器是一种权衡利弊的考虑,采取的是”及时失败”的策略,一旦迭代的数据被修改掉,就会抛出一个ConcurrentModificationException异常
开发的时候,可能需要根据不同的实际情况,选择合适的方案,3,4,5的程序例子都是可以使用的.
6.隐藏迭代器:
有时候,你可能会犯下面的错误:
目的:设计一个百分之百安全的类,代码如下:
1.线程不安全的复合操作1:
import java.util.Vector; public class UnsafeVectorOperation { public static Object getLast(Vector<?> list){ int lastIndex = list.size() - 1; return list.get(lastIndex); } public static void deleteLast(Vector<?> list){ int lastIndex = list.size() -1; list.remove(lastIndex); } }
线程B可能获取了list.size()-1的值之后,此时如果线程A执行了list.remove(lastIndex),那么线程B再接着执行return list.get(lastIndex);将会报ArrayIndexOutOfBoundsException异常
2.线程不安全的复合操作2:
如果给方法加上synchronized锁呢?
import java.util.Vector; public class UnsafeVectorOperation2 { public synchronized static Object getLast(Vector<?> list){ int lastIndex = list.size() - 1; return list.get(lastIndex); } public synchronized static void deleteLast(Vector<?> list){ int lastIndex = list.size() -1; list.remove(lastIndex); } }
结论是,线程仍然不安全,理由:
虽然按照上一题的中的线程A,B之间是安全的,但是,如果是下面的情况:
Vector list;
A线程:UnsafeVectorOperation2.getLast(list)
C线程:list.remove(list.size()-1);
所以上面的代码只能限制线程同时调用UnsafeVectorOperation2里的方法安全,一旦有其他线程也调用list,那么上面的代码就傻逼了.
3.如果给list上锁,使得复合操纵变为原子操作.
import java.util.Vector; public class UnsafeVectorOperation3 { public static Object getLast(Vector<?> list){ synchronized (list) { int lastIndex = list.size() - 1; return list.get(lastIndex); } } public static void deleteLast(Vector<?> list){ synchronized(list){ int lastIndex = list.size() -1; list.remove(lastIndex); } } }
UnsafeVectorOperation3 当中的确不存在线程不安全的问题了,但是其他线程对list的操作仍然线程不安全,这个不安全可以来自其他线程对UnsafeVectorOperation3的调用,例如:
Vector list; 线程B调用:deleteLast(list) 线程C执行: for(int i =0;i<list.size();i++) list.get(i); /****************************/ 假设size为10,C的i已经遍历到了9 如果B,C线程执行的情况是: C: 执行i& c213 lt;list.size() //i=9<size=10,继续遍历 B: 执行了deleteLast(list) //size将变为9 C: 执行list.get(i) //报ArrayIndexOutOfBoundsException异常
4.带有客户端锁的迭代,这下安全了,只不过…
synchronized(list){ for(int i =0;i<list.size();i++) list.get(i); }
在遍历期间,将会导致其他线程对list的访问,数据量越大,迭代越长,并发效率大大降低.很多时候得不偿失.
5.使用迭代器来迭代,解决并发效率低的问题:
至今所有的容器都并没有真正达到”既百分百安全,效率又很高”,而只能采取折中的方案.
for(Object o:list){ }
迭代器是一种权衡利弊的考虑,采取的是”及时失败”的策略,一旦迭代的数据被修改掉,就会抛出一个ConcurrentModificationException异常
开发的时候,可能需要根据不同的实际情况,选择合适的方案,3,4,5的程序例子都是可以使用的.
6.隐藏迭代器:
有时候,你可能会犯下面的错误:
目的:设计一个百分之百安全的类,代码如下:
import java.util.HashSet; import java.util.Random; import java.util.Set; public class HiddenIterator { private final Set<Integer> set = new HashSet<Integer>(); public synchronized void add(Integer i){ set.add(i); } public synchronized void remove(Integer i){ set.remove(i); } public void addTenRandomNum(){ Random r = new Random(); for(int i = 0;i<10;i++){ add(r.nextInt()); } //容易犯错误的地方,set.toString()在set集合里会进行迭代操作,而并没有上锁 //在集合的操作里面,有些容易让人忘记的迭代操作: toString,containsAll,removeAll,retainAll //这些间接迭代的操作都有可能抛出ConcurrentModificationException异常 System.out.println("DEBUG: added ten elements to "+set.toString()); } }
相关文章推荐
- 转:java多线程--同步容器
- java 多线程 同步类容器与并发类容器
- 跟着实例学习java多线程8-同步容器类的问题
- Java多线程之同步容器与并发容器
- Java多线程之同步类容器与并发容器
- 【Java多线程】共享变量&同步-异步容器&线程局部变量
- Java学习笔记—多线程(同步容器和并发容器)
- 初学Java多线程:使用Synchronized关键字同步类方法
- 浅谈Java多线程的同步问题
- 浅谈Java多线程的同步问题
- 2011-09-07 java多线程临界资源同步和调度问题,遇到困难加锁和解锁问题
- java(多线程)实现高性能数据同步
- java基础之:多线程实现/启动/状态+同步+线程池
- 菜鸟课堂:详解Java多线程开发中的数据同步
- java多线程实现火车售票系统 以及java中的同步的实现 同步块 和同步方法同时 同步
- java 多线程、线程池及同步
- Java多线程 同步 锁 条件对象
- 浅谈Java多线程的同步问题
- java多线程学习2-同步
- 浅谈Java多线程的同步问题