[关闭]
@zero1036 2017-03-14T09:11:03.000000Z 字数 1783 阅读 1158

Vector源码分析

Java-Base


简介

Vector矢量队列,继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口。支持相关的添加、删除、修改、遍历等功能。使用方法与ArrayList相似,主要区别在于Vector的方法是synchronized,相对线程安全。使用方法参考:ArrayList源码分析

继承关系:

  1. java.lang.Object
  2. java.util.AbstractCollection<E>
  3. java.util.AbstractList<E>
  4. java.util.Vector<E>
  5. public class Vector<E>
  6. extends AbstractList<E>
  7. implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}

相对线程安全

参考:《深入理解Java虚拟机--JVM高级特性与最佳实践》

按照线程安全的“安全程度”由强至弱来排序,可以将Java语言中各种操作共享的数据分为以下5类:不可变、绝对线程安全、相对线程安全、线程兼容与线程对立。

绝对的线程安全的定义:一个类要达到“不管运行时环境如何,调用者都不需要任何额外的同步措施”通常需要付出很大的,甚至有时候是不切实际的代价。在Java API中标注自己是线程安全的类,大多数是不是绝对的线程安全。java.util.Vector就是这样的例子。Vector的add()、get()、size()方法都是被synchronized修饰,但是,即使它所有的方法都是被修饰成同步,也不意味着调用它的时候永远都不在需要同步手段了。

证明例子:

  1. private static Vector<Integer> vector = new Vector<Integer>();
  2. public static void main(String[] args) {
  3. while (true) {
  4. for (int i = 0; i < 10; i++) {
  5. vector.add(i);
  6. }
  7. Thread removeThread = new Thread(new Runnable() {
  8. public void run() {
  9. for (int i = 0; i < vector.size(); i++) {
  10. vector.remove(i);
  11. }
  12. }
  13. });
  14. Thread getThread = new Thread(new Runnable() {
  15. public void run() {
  16. for (int i = 0; i < vector.size(); i++) {
  17. // 尝试加入首先判断i是否在vector size范围内,结果同样报错,
  18. // if (i < vector.size()) {
  19. // continue;
  20. // }
  21. vector.get(i);
  22. }
  23. }
  24. });
  25. removeThread.start();
  26. getThread.start();
  27. //不要同时产生过多的线程,否则会导致操作系统假死
  28. while (Thread.activeCount() > 20) ;
  29. }
  30. }

运行结果:执行例子get()会报错:java.lang.ArrayIndexOutOfBoundsException

尝试用先行发生原则分析是否绝对线程安全:
1. 程序次序:不满足,remove(i)get(i)在控制流顺序没有先行发生关系;
2. 管程锁定:不满足,remove(i)get(i)方法都是synchronized修饰,但各自持有不同的锁,不满足管程锁定要求的同一个锁;
3. volatile变量:不满足,没有volatile修饰变量,无视;
4. 线程启动:不满足,removeThread.start()先与vector.remove(i)getThread.start()先于vector.get(i),但后两者明显没有关系;
5. 线程终止:不满足;
6. 线程中断:不满足;
7. 对象终结:不满足,不存在对象终结的关系;
8. 传递性:不满足,加入size()验证作为参考,假定A是remove(),B是size()验证,C是get(),B先于C,但A可能介乎于BC之间,也可能在B之前。因此不符合传递性。

结论:Vector作为相对线程安全对象,其单个方法带Synchronized修饰,是相对线程安全的,但Vector方法之间不是线程安全的,不能保证多个方法作用下的数据一致性。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注