为啥 Vector<String> 在以多线程样式访问它时不以同步方式运行 [重复]

Posted

技术标签:

【中文标题】为啥 Vector<String> 在以多线程样式访问它时不以同步方式运行 [重复]【英文标题】:Why Vector<String> is not behaving in synchronized way while accessing it in multithreaded style [duplicate]为什么 Vector<String> 在以多线程样式访问它时不以同步方式运行 [重复] 【发布时间】:2021-05-22 03:09:35 【问题描述】:

根据我的理解,如果一个线程已经在访问它,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 次连续添加或删除。我在这里缺少什么?请帮忙。

【问题讨论】:

【参考方案1】:
    Vector 保证单个操作的原子性 向量不保证操作序列的原子性

在有问题的代码中,

    addremove 操作单独(独立)同步 - 在任何给定时间,只能对对象执行此操作中的一个 随着时间的推移,这些操作的不同调用不会同步

如果您需要跨一组操作进行同步,

    在集合上显式同步 在当前情况下,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);
    

【讨论】:

以上是关于为啥 Vector<String> 在以多线程样式访问它时不以同步方式运行 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Vector<String> 在以多线程样式访问它时不以同步方式运行 [重复]

为啥 make_unique to vector::back() 创建另一个副本?

为啥我在尝试将元素添加到 vector<vector<int>>(矩阵实现)时出现段错误?

为啥这段代码可以正常工作? (vector.clear(), vector<vector<int>>)

为啥 std::vector<bool> 没有 .data()?

为啥可以从函数返回“向量”?