为什么Vector<String>在以多线程样式访问时不以同步方式运行
根据我的理解,如果一个线程已经在访问它,Vector 应该阻止其他线程的整个集合。我在尝试着
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
public class MyTest1{
// static ArrayList<String> l1 = new ArrayList<>(Arrays.asList("A", "B", "C"));
static Vector<String> l1 = new Vector<>(Arrays.asList("A", "B", "C"));
// static List<String> l1 = Collections.synchronizedList(Arrays.asList("A", "B", "C"));
public static void main(String[] args) {
Thread t1 = new Thread(new MyThread1());
Thread t2 = new Thread(new MyThread2());
t1.start();
t2.start();
System.out.println(Thread.currentThread() + "adding X " + l1.add("X"));
System.out.println(Thread.currentThread() + "adding Y " + l1.add("Y"));
System.out.println(Thread.currentThread() + "adding Z " + l1.add("Z"));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(l1);
}
static class MyThread1 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread() + "adding D " + l1.add("D"));
System.out.println(Thread.currentThread() + "adding E " + l1.add("E"));
System.out.println(Thread.currentThread() + "adding F " + l1.add("F"));
}
}
static class MyThread2 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread() + "removing A " + l1.remove("A"));
System.out.println(Thread.currentThread() + "removing B " + l1.remove("B"));
System.out.println(Thread.currentThread() + "removing C " + l1.remove("C"));
}
}
}
输出:
Thread[main,5,main]adding X true
Thread[Thread-1,5,main]removing A true
Thread[Thread-1,5,main]removing B true
Thread[Thread-0,5,main]adding D true
Thread[Thread-1,5,main]removing C true
Thread[main,5,main]adding Y true
Thread[Thread-0,5,main]adding E true
Thread[main,5,main]adding Z true
Thread[Thread-0,5,main]adding F true
[X, D, Y, E, Z, F]
输出不应该是这样的。对于特定线程,它应该是 3 个连续的添加或删除。我在这里缺少什么?请帮忙。
回答
- Vector保证单个操作的原子性
- Vector 不保证操作序列的原子性
在有问题的代码中,
add和remove操作单独(独立)同步 - 在任何给定时间,只能在对象上执行此操作之一- 随着时间的推移,它不会在这些操作的不同调用之间同步
如果您需要跨一组操作进行同步,
- 在集合上显式同步
- 在当前情况下,
ArrayList与同步一起使用时应该没问题
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class MyTest1 {
static List<String> l1 = new ArrayList<>(Arrays.asList("A", "B", "C"));
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (l1) {
System.out.println(Thread.currentThread() + "removing A " + l1.remove("A"));
System.out.println(Thread.currentThread() + "removing B " + l1.remove("B"));
System.out.println(Thread.currentThread() + "removing C " + l1.remove("C"));
}
});
Thread t2 = new Thread(() -> {
synchronized (l1) {
System.out.println(Thread.currentThread() + "removing A " + l1.remove("A"));
System.out.println(Thread.currentThread() + "removing B " + l1.remove("B"));
System.out.println(Thread.currentThread() + "removing C " + l1.remove("C"));
}
});
t1.start();
t2.start();
synchronized (l1) {
System.out.println(Thread.currentThread() + "adding X " + l1.add("X"));
System.out.println(Thread.currentThread() + "adding Y " + l1.add("Y"));
System.out.println(Thread.currentThread() + "adding Z " + l1.add("Z"));
}
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(l1);
}
}
THE END
二维码