同步容器类

Vector、HashTable,我用的很少;Vecotr的实现和ArrayList挺接近的,不同的是Vector中很多的方法都用synchronized进行了同步。在不强调线程安全地时候用ArrayList,在需要线程安全地时候用Vector。
实现线程安全的方法:把它们的状态封装起来,并对每个公有方法都进行同步,使得每次都只有一个线程能访问容器的状态。

同步容器类问题

在某些情况下需要额外的客户端加锁来保护复合操作:

  1. 迭代,遍历容器中所有元素
  2. 跳转,根据当前顺序找到一下个元素
  3. 条件运算,若没有则添加

执行"先检查再运行"的demo

 1 public class VectorDemo {
 2     // 获取最后一个元素
 3     public static Object getLast(Vector list) {
 4         int lastIndex = list.size() - 1;
 5         return list.get(lastIndex);
 6     }
 7     // 删除最后一个元素
 8     public static void deleteLast(Vector list) {
 9         int lastIndex = list.size() - 1;
10         list.remove(lastIndex);
11     }
12 }

在客户端中给Vector加上锁,获得一个线程安全的版本:

 1 public class VectorDemo {
 2     // 获取最后一个元素
 3     public static Object getLast(Vector list) {
 4         synchronized (list) {
 5             int lastIndex = list.size() - 1;
 6             return list.get(lastIndex);
 7         }
 8     }
 9     // 删除最后一个元素
10     public static void deleteLast(Vector list) {
11         synchronized (list) {
12             int lastIndex = list.size() - 1;
13             list.remove(lastIndex);
14         }
15     }
16 }

支持客户端加锁,可以创建一些新的操作,只要知道应该使用哪一个锁,那么这些新的操作就与容器的其他操作一样都是原子操作。在这个例子中getLast和deleteLast与Vector中其他的方法都共享一把锁,也就是Vector实例自己,同一时刻只能进入其中的一个synchronized代码块中。

在同步容器类中,这些复合操作在没有客户端加锁的情况下仍然是线程安全的,在其他线程并发修改容器的时候,可能会有意料之外的行为。

两个方法都是线程安全的,但是组合起来会导致异常。可以在客户端加锁来解决不可靠迭代的问题,但是要牺牲一些伸缩性。通过在迭代期间持有Vector的锁可以防止其他线程在迭代期间修改Vector。

迭代器与ConcurrentModificationException

对容器进行迭代的标准方式都是用Iterator。在同步容器类中,进行迭代时并没有考虑到并发修改,而是用的"及时失败",终于搞懂了快速失效了。这意味着在迭代时容器被修改将会抛出一个ConcurrentModificationException异常。

这种及时失败的迭代器并不是一种完备的处理机制,而只是善意地捕获并发错误,因此只能作为并发问题的预警指示器。采用的方法是,将计数器的变化与容器关联起来:如果在迭代期间计数器被修改,那么hasNext或next将抛出ConcurrentModification。然而这种检查是在没有同步的情况下进行的,因此可能会看到失效值,而迭代可能并没有意识到已经发生了修改。

为什么不希望在迭代的时候加锁:

  1. 容器的规模很大,或者在每个元素上执行的操作时间很长,那么这些线程将长时间等待。
  2. 一直持有一个锁,可能产生死锁,降低程序的可伸缩性,持有锁的时间越长,锁上的竞争越激烈,如果许多线程都等待着锁被释放,那么将极大地降低吞吐量和CPU的利用率。

隐藏迭代器

加锁可以防止迭代器抛出ConcurrentModificationException,但是要记住在所有对共享容器进行迭代的地方都需要加锁。

如果状态与保护它的同步代码之间相隔越远,那么开发人员就越容易忘记在访问状态的时候使用正确的同步。正如封装对象的状态有助于维持不变性的条件一样,封装对象的同步机制同样有助于确保实施同步策略。

容器的hashCode和equals方法同样会间接地执行迭代操作,当容器所谓另一个容器的元素或者键值时就会出现这种情况。

转载于:https://www.cnblogs.com/tuhooo/p/8073718.html

Java并发编程(十三)同步容器类相关推荐

  1. Java并发编程:同步容器

    为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步容器.并发容器.阻塞队列.Synchronizer(比如CountDownLatch).今天我们就来讨论下同步容器. ...

  2. 【Java并发编程 】同步——volatile 关键字

    英 /ˈvɒlətaɪl/ 我了太噢(记不住单词怎么读) 一.volatile的介绍? volatile是一个轻量级的synchronized,一般作用与变量,在多处理器开发的过程中保证了内存的可见性 ...

  3. Java并发编程—线程同步类

    原文作者:洲洋1984 原文地址:Java 并发包中的高级同步工具 Java 中的并发包指的是 java.util.concurrent(简称 JUC)包和其子包下的类和接口,它为 Java 的并发提 ...

  4. Java 并发编程之同步工具类闭锁 CountDownLatch

    Java 同步工具类CountDownLatch相当于一个计数器,假设一个方法,等待一个计数器从初始值5变为0,每使用一次countdown()方法,计数器的值减少1,当计数器的值为0时,触发某件事. ...

  5. Java 并发编程之同步工具类 Exchanger

    Exchanger 交换器,用于两个线程之间交换数据. 线程1调用exchange()方法,然后进行线程阻塞,等待线程2调用exchange()方法交换数据,线程2调用exchange()方法后,两个 ...

  6. Java 并发编程之同步工具类栅栏 CyclicBarrier

    CyclicBarrier 用来阻塞一组线程,等待线程完成后才开始某件事情. 例如,开启5个线程,每个线程使用await方法开始阻塞,等待5个线程都完成,才开始执行await方法后面的代码. publ ...

  7. Java 并发编程之同步工具类信号量 Semaphore

    Semaphore 可以理解为一个阈值,正在进行的操作数量不能超过此阈值,可以用来限制资源的访问,或者控制某个队列中对象的个数,也就是控制同时执行的线程的数量. 主要有acquire,release两 ...

  8. Java并发编程—常见面试题

    建议: 学习java并发前需要先掌握JVM知识 关于下面问题档案的详细解析都在后面推荐的相关系列文章中 一.线程安全相关 1.什么叫线程安全? 线程安全就是说多线程访问同一代码,不会产生不确定的结果. ...

  9. 海子Java并发编程学习总结

    2019独角兽企业重金招聘Python工程师标准>>> Java并发编程:进程和线程之由来 Java并发编程:如何创建线程? Java并发编程:Thread类的使用 Java并发编程 ...

  10. java并发编程并发容器_Java并发编程:同步容器

    为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步容器.并发容器.阻塞队列.Synchronizer(比如CountDownLatch).今天我们就来讨论下同步容器. ...

最新文章

  1. Google、高通都在研究的芯片架构,是他们对抗ARM的武器
  2. jquery.each读取json数据
  3. oracle异常如何处理,ORACLE异常处理总结
  4. [Xcode 实际操作]八、网络与多线程-(19)使用RunLoop使PerformSelector方法延迟动作的执行...
  5. 三行代码实现快速排序
  6. mysql 不join的原因
  7. python将学生信息保存到文件中_Python statsmodels OLS:如何将学习的模型保存到文件中...
  8. 隐藏我的电脑中的多余图标
  9. 5. 在Windows上安装Git
  10. 【Matlab学习笔记】【函数学习】nargin 参数
  11. 常见的一些正则表达式!
  12. HTML超好看的个人主页源码+支持响应式
  13. 【Linux】Linux设备驱动开发详解:基于最新的Linux 4.0内核
  14. 数学四大思想八大方法_数学四大思想方法
  15. fbreader android源码分析,FBReader 源码阅读笔记(二)
  16. sqlserver pivot 动态行转列且一行转多列的解决方案
  17. html5的calc,CSS 计算属性 calc()的完整指南(下)
  18. 计算机蓝屏代码0xc0000020,Win10系统运行程序提示“损坏的映像 错误0xc0000020”怎么解决...
  19. B站这个视频我是跪着看完的
  20. sap进阶系列(14):第一篇:财务总览之合并会计报表(1)

热门文章

  1. 一些或许用的到的小Demo
  2. Android Studio导入github项目详解
  3. 深入浅出多线程系列之四:简单的同步 lock
  4. Java Stream流的概念
  5. windows mobile 鼠标等待
  6. Slog3_如何使用Python与Mysql进行数据交互
  7. Codeforces 458C - Elections
  8. 1012: [JSOI2008]最大数maxnumber
  9. Mathematica该注意的两种特殊的输入方式(blanksequence and ruledelayed)
  10. 怎样把android应用部署到手机上