为什么在以多线程方式访问时,Vector 不以同步方式运行

13 浏览
0 Comments

为什么在以多线程方式访问时,Vector 不以同步方式运行

根据我的理解,如果已经有一个线程正在访问Vector,那么Vector应该阻塞整个集合,以防止其他线程的访问。我正在尝试使用以下代码:\n

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 Vector l1 = new Vector<>(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() + "添加 X " + l1.add("X"));
        System.out.println(Thread.currentThread() + "添加 Y " + l1.add("Y"));
        System.out.println(Thread.currentThread() + "添加 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() + "添加 D " + l1.add("D"));
            System.out.println(Thread.currentThread() + "添加 E " + l1.add("E"));
            System.out.println(Thread.currentThread() + "添加 F " + l1.add("F"));
        }
    }
    static class MyThread2 implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread() + "移除 A " + l1.remove("A"));
            System.out.println(Thread.currentThread() + "移除 B " + l1.remove("B"));
            System.out.println(Thread.currentThread() + "移除 C " + l1.remove("C"));
        }
    }
}

\n输出结果应该不是这样的。应该是一个特定线程的3次连续添加或移除操作。我在这里漏掉了什么?请帮忙解答。

0
0 Comments

问题出现的原因是,Vector类只能保证单个操作的原子性,但不能保证一系列操作的原子性。在给定的代码中,add和remove操作是独立同步的,也就是说在任何给定的时间,只能对对象执行其中一个操作。然而,它并不能在不同的操作调用之间同步。

要实现一组操作的同步,需要显式地在集合上进行同步。在当前情况下,如果与同步一起使用,则ArrayList应该是可以的。

下面的代码演示了使用ArrayList进行同步的方法:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class MyTest1 {
    static List 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);
    }
}

在这个例子中,通过在操作之前使用synchronized关键字来同步ArrayList对象,确保了在多线程环境下的安全访问。同时,使用同步块来保证多个操作之间的同步。

0