@zero1036
2016-12-10T11:06:55.000000Z
字数 1854
阅读 1413
Java-JVM
先行发生原则是判断数据是否存在竞争、线程是否安全的主要依据。
摘自:《深入理解Java虚拟机——JVM高级特性与最佳实践(第2版)》
线程安全类型Vector,只是相对线程安全,并非绝对线程安全
private static Vector<Integer> vector = new Vector<Integer>();
public static void main(String[] args) {
while (true) {
for (int i = 0; i < 10; i++) {
vector.add(i);
}
Thread removeThread = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < vector.size(); i++) {
vector.remove(i);
}
}
});
Thread getThread = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < vector.size(); i++) {
// 尝试加入首先判断i是否在vector size范围内,结果同样报错,
// if (i < vector.size()) {
// continue;
// }
vector.get(i);
}
}
});
removeThread.start();
getThread.start();
//不要同时产生过多的线程,否则会导致操作系统假死
while (Thread.activeCount() > 20) ;
}
}
remove(i)
与get(i)
在控制流顺序没有先行发生关系;remove(i)
与get(i)
方法都是synchronized修饰,但各自持有不同的锁,不满足管程锁定要求的同一个锁;removeThread.start()
先与vector.remove(i)
,getThread.start()
先于vector.get(i)
,但后两者明显没有关系;size()
验证作为参考,假定A是remove()
,B是size()
验证,C是get()
,B先于C,但A可能介乎于BC之间,也可能在B之前。因此不符合传递性。结论:Vector作为相对线程安全对象,其单个方法带Synchronized修饰,是相对线程安全的,但Vector方法之间不是线程安全的,不能保证多个方法作用下的数据一致性。执行例子get()
会报错:java.lang.ArrayIndexOutOfBoundsException
。