同步注意事项(1)避免过度同步

标签: java concurrent 并发 线程池
752人阅读 评论(0) 收藏 举报
分类:

在一个同步区域内部,不要调用设计成要被覆盖的方法,这类方法被称为外来方法,调用这种方法会放生许多不必要的异常,而且有时候很难检查,

举例说明,下面的类是用观察者模式做的,允许客户端在将元素添加到集合中时预定通知,该类是在ForwardingSet上实现的,下面是代码:

类ObservableSet:

类SetObserver:

ObservableSet类中会调用addObserver方法预定通知。

如果粗略的检验一下,ObserverbleSet很正常。例如下面的程序,正常打印0~99:



下面试下更复杂的例子,当值为23的时候,这个观察者自动删除

最开始,你可能以为,他会打印出0~23然后结束进程,实际上它会抛出ConcurrentModificationException。因为当调用addObserver方法时,它加了一个类锁synchronized(observers),而removeObsserver方法同样也加了类锁(observers),当s.removeObserver调用的时候,锁正被它外部的addObserver方法占用,此时就会报错。

还有一个比较奇特的例子,将set.addObserver换成这一段:

此时,没有再遭遇异常,但是会产生死锁。因为主线程一直在等待后台线程对观察者的删除,这是造成这种情况的原因(线程池所做的线程都是后台线程)

要解决这个问题有一个非常好的办法,java1.5发行后,java的concurrent包中提供了一个并发集合,称作:CopyOnWriteArrayList.这是专门为此定制,我们只要将ObserverSet的第一行换下声明为CopyOnWriteArrayLIst就可以了。它是通过拷贝整个底层数组,实现所有的写操作


查看评论

避免过度同步(笔记)

简述: 《Effective Java》
  • anialy
  • anialy
  • 2014-09-10 00:03:58
  • 862

避免过多的同步

原因:过多的同步可能会导致性能降低,死锁,甚至不确定的行为。为了避免死锁的危险,在一个被同步的方法或是代码块中,永远不要放弃对客户的控制。换句话说,在一个被同步的区域内部,不要调用一个可被改写的公有或...
  • dengjie532054105
  • dengjie532054105
  • 2010-02-08 17:21:00
  • 288

Java --- Guava Collection API javadoc

Java --- Guava Collection javadoc翻译 com.google.common.collect包 接口 BiMap Bimap也叫双向ma...
  • dreamsofa
  • dreamsofa
  • 2015-10-09 16:25:51
  • 830

Guava简介

博客原文请参考:http://zhuqiuhui.space/Blogs/2017/03/guava-api-collect.html Guava 是一个 Google 的基于 java1.6的类库...
  • zhuqiuhui
  • zhuqiuhui
  • 2017-03-23 21:46:37
  • 674

java并发编程之过度同步

过度同步可能造成性能减低、死锁,甚至不确定的问题。     在一个被同步的区域内部,不要调用被设计成被复写(覆盖)的方法。从包含该同步区域的类的角度来看,这样的方法是外来的。这个类不知道该方法会做些...
  • u013846611
  • u013846611
  • 2014-03-02 11:05:35
  • 594

effective java避免过度同步

过度同步可能会导致性能降低,死锁,甚至不确定的行为。为了避免火星失败和安全性失败,在一个被同步的方法或者代码快中,永远不要放弃对客户端的控制。将外来方法调用一处同步的代码块 建立快照 使用并发集合...
  • chai_ge_ge
  • chai_ge_ge
  • 2017-08-20 16:54:54
  • 168

同步注意事项(1)避免过度同步

在一个同步区域内部,不要调用设计成要被覆盖的方法,这类方法被称为外来方法,调用这种方法会放生许多不必要的异常,而且有时候很难检查, 举例说明,下面的类是用观察者模式做的,允许客户端在将元素添加到集合...
  • u012291108
  • u012291108
  • 2016-06-01 16:07:06
  • 752

effective java(16) 之复合优先于继承

effective java 之复合优先于继承 1、 继承是实现代码重用的重要手段,但它并非永远是完成这项工作的最佳工具,不恰当的使用会导致程序变得很脆弱。 在包的内部使用继承是非常安全的...
  • dingjianmin
  • dingjianmin
  • 2017-10-18 21:27:26
  • 110

同步机构 模拟实现同步机构 操作系统实验

  • 2009年12月30日 17:02
  • 462KB
  • 下载

Java并发学习之十二——在同步的类里安排独立属性

本文是学习网络上的文章时的总结,感谢大家无私的分享。 当你使用synchronized关键字来保护代码块时,你必须通过一个对象的引用作为参数。通常,你将会使用this关键字来引用执行该方法的对象,但...
  • junshuaizhang
  • junshuaizhang
  • 2014-09-15 16:49:06
  • 2049
    个人资料
    持之以恒
    等级:
    访问量: 19万+
    积分: 2305
    排名: 2万+
    最新评论