多线程:Vector是线程安全的吗

线程安全,在java的多并发编程中是重要概念,意思是,多个线程同时操作一个对象,在各种不同情况下,都不会造成不同的后果。

一个经典问题,Vector到底是不是线程安全的?

 

很多人都会回答,是,vector是线程安全的。

诚然,不止是很多IT教材上是这么写的,就连JDK的作者写的注释也是这么说的。如下图(图为 JDK中Vector的源代码):注释中,红框标记的部分写着:如果你不需要线程安全的实现类,那就推荐你用ArrayList,而不是Vector。言外之意,就是说,Vector是线程安全的。

自己看了源码,发现,确实很多方法都有同步关键字synchronized,从而保证所有的对外接口都会以 Vector对象为锁,即,在vector内部,所有的方法都不会被多线程访问。

但是,单个方法的原子性(注:原子性,程序的原子性即不会被线程调度机制打断)并不能保证复合操作也具有原子性。


所以,这个问题的正确回答应该是:

虽然源代码注释里面说这个是线程安全的,因为确实很多方法都加上了同步关键字synchronized,但是对于复合操作而言,只是同步方法但并没有解决线程安全的问题。因为在两个原子操作之间存在间隙,在多线程环境中,完全有可能被其他线程获得 vector的 lock 并改变其状态。要真正达成线程安全,还需要以vector对象为锁,来进行操作。所以,如果是这样的话,那么用vector和ArrayList就没有区别了,所以,不推荐使用vector。


举个栗子:

if (!vector.contains(element)) 
    vector.add(element); 
    ...
}



这是经典的 put-if-absent 情况,尽管 contains, add 方法都正确地同步了,但作为 vector 之外的使用环境,仍然存在  race condition: 因为虽然条件判断 if (!vector.contains(element))与方法调用 vector.add(element);  都是原子性的操作 (atomic),但在 if 条件判断为真后,那个用来访问vector.contains 方法的锁已经释放,在即将的 vector.add 方法调用 之间有间隙,在多线程环境中,完全有可能被其他线程获得 vector的 lock 并改变其状态, 此时当前线程的vector.add(element);  正在等待(只不过我们不知道而已)。只有当其他线程释放了 vector 的 lock 后,vector.add(element); 继续,但此时它已经基于一个错误的假设了。

单个的方法 synchronized 了并不代表组合(compound)的方法调用具有原子性,使 compound actions  成为线程安全的可能解决办法之一还是离不开intrinsic lock (这个锁应该是 vector 的,但由 client 维护):

// Vector v = ...
    public  boolean putIfAbsent(E x) {
synchronized(v) { 
            boolean absent = !contains(x); 
            if (absent) { 
                add(x);
} 
}
        return absent; 
    }

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]中的错误信息是关于引用类型不匹配的错误。错误信息显示尝试将类型为`const std::vector<long unsigned int>`的表达式初始化为类型为`const std::vector<bool>&`的引用。这可能是因为在代码中使用了错误的类型或者在函数调用中传递了错误的参数类型。 引用\[2\]中的代码展示了如何使用`std::vector`存储`vtkActor*`类型的指针,并返回该向量。这段代码没有涉及到线程冲突的问题。 引用\[3\]中的代码展示了一个使用`std::future`和`std::async`的例子。在这个例子中,通过`std::async`创建了一个异步任务,并使用`std::future`来获取任务的结果。在主线程中,通过循环调用`future.wait_for`来检查任务的状态,直到任务完成。这段代码也没有涉及到线程冲突的问题。 综上所述,根据提供的引用内容,没有直接涉及到`std::vector`复制后的线程冲突问题。如果您有更具体的问题或者代码示例,请提供更多信息以便我能够更好地回答您的问题。 #### 引用[.reference_title] - *1* [ invalid initialization of reference of type ‘const std::vector<bool>&’](https://blog.csdn.net/qq_35102059/article/details/125193444)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [【DEBUG笔记】VTK中使用std::vector时报指针错误“读取位置xxx时发生访问冲突”](https://blog.csdn.net/orangecsy/article/details/76064773)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [std::future和std::promise和std::packaged_task](https://blog.csdn.net/yizhiniu_xuyw/article/details/115194980)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值