`
zhouchaofei2010
  • 浏览: 1104216 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java并发编程实战-第5章-基础构建模块

 
阅读更多

java并发编程实战-第5章-基础构建模块

  第4章中,介绍的构造线程安全类中的技术中,委托是创建线程安全类的一个最有效策略。

  java平台类中包含了丰富的并发基础构建模块,例如线程安全类容器和同步类工具。本章将介绍其中的一些最有用的模块以及使用这些模块构建并发应用程序的一些常用模式

  

  

5.1 同步容器类

    早期的有vector、Hashtable 、以及Collections.synchronizedXxx构建的容器

    

5.1.1 同步容器类的问题

   同步类容器是线程安全的,但在某些情况下需要客户端加锁来保护复合操作。比如常见的迭代

   

   list 5-1 在Vector上可能导致混乱结果的复合操作 

   public static Object getLast(Vector list) {

    int lastIndex = list.size() - 1;

    return list.get(lastIndex);

}

 

public static void deleteLast(Vector list) {

   int lastIndex = list.size() - 1;

   list.remove(lastIndex);

}

 

    A ->size(10)------------->get(9)->出错   

    B ->size(10)->remove(9)

    

    在客户端加锁解决如上问题

    public static Object getLast(Vector list) {

    synchronized (list) {

        int lastIndex = list.size() - 1;

        return list.get(lastIndex);

    }

}

 

public static void deleteLast(Vector list) {

   synchronized (list) {

       int lastIndex = list.size() - 1;

       list.remove(lastIndex);

   }

}

 

 

    

    

    

    

5.1.2 Iterators and Concurrentmodificationexception

 

List<Widget> widgetList

   = Collections.synchronizedList(new ArrayList<Widget>());

...

// May throw ConcurrentModificationException

for (Widget w : widgetList)

   doSomething(w);

 

  为解决这个问题,则可以再迭代期间对容器加锁,但是容器内容很多的情况下,那么持有锁的时间会变长,在锁上的竞争更激烈。如果不希望在迭代期间对容器加锁,那么

  一种替代方法是"克隆"容器

  

  

5.1.3 隐藏的迭代器

   

   像set.toString(),containsAll、removeAll和retainAll等方法,在这些间接的迭代操作都可能抛出Concurrentmodificationexception

   

   

   例子: 

public class HiddenIterator {

   @GuardedBy("this")

   private final Set<Integer> set = new HashSet<Integer>();

 

   public synchronized void add(Integer i) { set.add(i); }

   public synchronized void remove(Integer i) { set.remove(i); }

 

   public void addTenThings() {

       Random r = new Random();

       for (int i = 0; i < 10; i++)

           add(r.nextInt());

       System.out.println("DEBUG: added ten elements to " + set);   //隐藏的迭代器

  }

}

 

 

If HiddenIterator wrapped the HashSet with a synchronizedSet, encapsulating the synchronization, this sort of error would not occur.

5.2 并发容器 

    java5.0 提供了很多并发容器来改进同步容器的性能。

    

    通过并发容器代替同步容器,可以极大地提高伸缩性并降低风险

    

    ConcurrentHashMap 

    CopyOnWriteArrayList 

    Queue 实现有传统的FIFO队列ConcurrentLinkedQueue 、优先队列 PriorityQueue ,这些队列的操作不会阻塞、如果没有数据则返回null

    and BlockingQueue,扩展了Queue,如果为空,则阻塞等待。在生产者-消费者模式中非常有用(5.3介绍)

    

5.2.1 ConcurrentHashMap

     分段锁机制

     可以容忍并发的修改,size和isEmpty 是估计值,但是这些方法在并发环境中作用很小,因为他们的返回值总在变化。这些操作的需求被弱化了,换取了其他更重要的操作的性能优化,比如put、get、containKey、remove等

     

5.2.2 额外的原子Map操作

      a number of common compound operations such as put-if-absent, remove-if-equal, and replace-if-equal are implemented as atomic operations and specified by the ConcurrentMap interface

     如果需要在同步容器中添加这些操作,则需要考虑是否需要ConcurrentMap

5.2.3. CopyOnWriteArrayList

     写入时复制ArrayList,底层指向一个不可变的数组,迭代时只要保证可见性即可。每次修改时,都会创建并重新发布一个新的容器副本(复制底层数组)。

     所以仅当迭代操作远远多于修改操作时才应该使用CopyOnWriteArrayList,比如事件通知系统

5.3  阻塞队列和生产者消费者模式

     一种最常见的生产者-消费者设计模式就是线程池与工作队列的组合

     

     Bounded queues are a powerful resource management tool for building reliable applications: 

     they make your program more robust to overload by throttling activities that threaten to produce more work than can be handled.

 

5.3.1 示例:桌面搜索

      生产者-消费者 阻塞队列 的应用

      

5.3.2 串行线程封闭

      生产者-消费者设计与阻塞队列一起,促进了线程封闭,从而将对象的所有权从生产者交给消费者

      

5.3.3 双端队列与工作密取(Deques and Work Stealing)

      

       在生产者-消费者设计,所有消费者共享一个队列

       在工作密取设计中,每个消费者都有各自的双端队列。

       most of the time they access only their own deque, reducing contention. When a worker has to access another's queue, it does so from the tail rather than the head, further reducing contention

       

       

       Work stealing is well suited to problems in which consumers are also producerswhen performing a unit of work is likely to result in the identification of more work.

      

     例如,网页爬虫处理一个页面时会发现更多的页面需要处理。类似的搜索图算法

     

5.4 阻塞方法与中断方法

 

    出现InterruptedException,代码必须对此进行处理。对于类库来说,2中选择

    1、传递InterruptedException

    2、恢复中断

    

    3、捕获但不处理 (特殊情况下使用,即对Thread进行扩展,并且能调用栈上所有高层的代码,。第7章进一步介绍取消和中断)

 

5.5 同步工具

   Blocking queues

           

   semaphores 信号量

      Counting semaphores(计数信号量) are used to control the number of activities that can access a certain resource or perform a given action at the same time [CPJ 3.4.1]. 

      例如:资源池、BoundedHashSet 

   barriers 栅栏

     Barriers are similar to latches in that they block a group of threads until some event has occurred [CPJ 4.4.3]. 

     The key difference is that with a barrier, all the threads must come together at a barrier point at the same time in order to proceed. Latches are for waiting for events; barriers are for waiting for other threads

     barriers等其他线程

     latches 等事件

     CyclicBarrier 的应用

  

   latches 闭锁

      CountDownLatch  参考jdk文档例子

      

5.5.2 FutureTask  (also acts like a latch)

      Future.get(); The behavior of Future.get depends on the state of the task. If it is completed, get returns the result immediately, and otherwise blocks until the task transitions to the completed state and then returns the result or throws an exception

5.5.4 semaphores

 

5.5.4 barriers

   应用1:并行迭代算法 例子:细胞自动化模拟

     

   应用2:Exchanger   参考jdk自带例子

5.6 构建高效且可伸缩的结果缓存

    改进过程:

    HashMap ->

    ConcurrentHashMap<A, V>(); ->

    -new ConcurrentHashMap<A, Future<V>>();

    f = cache.putIfAbsent(arg, ft); 代替 cache.put(arg, ft);

    

    ==》Factorizing Servlet that Caches Results Using Memoizer

 

 

第1部分小结:

 

1、It's the mutable state, stupid. [1]

 

All concurrency issues boil down to coordinating access to mutable state. The less mutable state, the easier it is to ensure thread safety.

 

2、Make fields final unless they need to be mutable.

 

3、Immutable objects are automatically thread-safe.

 

Immutable objects simplify concurrent programming tremendously. They are simpler and safer, and can be shared freely without locking or defensive copying.

 

4、Encapsulation makes it practical to manage the complexity.

 

You could write a thread-safe program with all data stored in global variables, but why would you want to? 

Encapsulating data within objects makes it easier to preserve their invariants; encapsulating synchronization within objects makes it easier to comply with their synchronization policy.

 

5、Guard each mutable variable with a lock.

 

6、 Guard all variables in an invariant with the same lock.

 

7、Hold locks for the duration of compound actions.

 

8、A program that accesses a mutable variable from multiple threads without synchronization is a broken program.

 

9、Don't rely on clever reasoning about why you don't need to synchronize.

 

10、Include thread safety in the design processor explicitly document that your class is not thread-safe.

 

11、Document your synchronization policy.

 

 

 

  

分享到:
评论

相关推荐

    《java并发编程实战》读书笔记-第5章-基础构建模块

    《java并发编程实战》读书笔记-第3章-对象的共享,脑图形式,使用xmind8制作 包括同步容器类、并发容器类、阻塞队列和生产者消费者模式、阻塞和中断方法、同步工具类。最后是构建高效且可伸缩的结果缓存

    Java并发编程实战

    第5章 基础构建模块 5.1 同步容器类 5.1.1 同步容器类的问题 5.1.2 迭代器与Concurrent-ModificationException 5.1.3 隐藏迭代器 5.2 并发容器 5.2.1 ConcurrentHashMap 5.2.2 额外的原子Map操作 5.2.3 ...

    Java并发编程实战2019.zip

    第5章 基础构建模块 第6章 任务执行 第7章 取消与关闭 第8章 线程池的使用 第9章 图形用户界面应用程序 第10章 避免活跃性危险 第11章 性能与可伸缩性 第12章 并发程序的测试 第13章 显式锁 第14章 构建...

    Java 并发编程实战

    第5章 基础构建模块 5.1 同步容器类 5.1.1 同步容器类的问题 5.1.2 迭代器与Concurrent-ModificationException 5.1.3 隐藏迭代器 5.2 并发容器 5.2.1 ConcurrentHashMap 5.2.2 额外的原子Map操作 5.2.3 ...

    私塾在线 高级java软件架构师实战培训视频教程 阶段一 代码及目录 142-148 讲 共148讲 结束了

    本套高级Java软件架构师实战培训视频教程是私塾在线推出的系列课程,旨在提升学员的Java编程技能和软件架构设计能力。课程覆盖了142至148讲,全面讲解了从基础架构到高级应用的诸多关键知识点,以下是部分核心内容的...

    重磅!《Go Web编程实战派从入门到精通》随书源码开源啦,Go语言-Web-goWebActualCombat.zip

    5. **并发编程**:Go语言的goroutine和channel是其并发编程的核心,通过它们可以轻松地实现多任务并行处理,提高Web服务的响应速度。 6. **错误处理**:Go语言鼓励显式处理错误,项目中可能展示了如何优雅地捕获和...

    java高手真经源码-EJB和开源

    5. 第五章:Spring在EJB和SHH2中的作用,详细介绍Spring如何作为整体框架,协调各个组件。 6. 第六章:实战篇,提供实际案例,演示EJB与SHH2整合开发的全过程。 7. 第八章:进阶话题,讨论EJB的高级特性,如集群、...

    李兴华java开发实战经典讲义(PDF格式)

    6. **多线程**:030901_【第9章:多线程】_认识多线程笔记.pdf,讲述了Java中的并发编程,如何创建和管理线程,理解线程同步与通信的概念,以及Java提供的线程API。 7. **图形界面**:031809_【第18章:图形界面】_...

    使用Java理解程序逻辑第12章.zip

    在本课程"使用Java理解程序逻辑第12章"中,我们主要探讨的是Java编程语言在构建复杂程序逻辑方面的应用。作者田超凡通过一系列深入浅出的讲解,旨在帮助学习者掌握Java的核心概念和技巧,提升编程能力。在这个章节中...

    Java 性能优化实战 21 讲

    5. **并发编程优化**:理解Java并发库,如线程池(ThreadPoolExecutor)、Future、Callable、Lock接口,以及如何避免死锁、活锁和饥饿。 6. **CPU和磁盘I/O优化**:降低系统调用,减少磁盘I/O操作,使用NIO(非阻塞...

    Java经典实例(第2版).pdf 高清pdf 下载.rar

    《Java经典实例(第2版)》是一本深入探讨Java编程技术的书籍,以其高清PDF格式提供下载。这本书是Java开发者的重要参考资料,尤其适合初学者和有经验的程序员提升技能。书中涵盖了各种Java编程的核心概念和技术,通过...

    Java完美编程(第三版)

    《Java完美编程(第三版)》是一本深入探讨Java编程技术的权威著作,旨在帮助读者掌握Java编程的核心概念和技术,从而实现代码的高效、稳定与优雅。本书针对Java的最新版本进行更新,确保覆盖了现代Java开发的关键知识...

    Java EE核心框架实战

    《Java EE核心框架实战》是一本专为Java开发者设计的进阶教程,旨在深入解析企业级应用开发中广泛采用的SSM(Spring、Spring MVC、MyBatis)和SSH(Struts、Spring、Hibernate)两大主流框架。这些框架是Java EE世界...

    Java课后答案

    ### 第五章:多线程编程 - **线程的概念**:理解线程的基本原理及其在并发编程中的作用。 - **创建线程的方式**:通过继承Thread类或实现Runnable接口来创建线程。 - **线程调度与生命周期**:分析线程的状态变化...

    Java程序设计教程(第七版).zip

    《Java程序设计教程(第七版)》是一本深入讲解Java编程技术的权威教材,适合初学者及有一定经验的程序员作为学习参考。此压缩包包含了该教程的全部内容,旨在帮助读者掌握Java语言的核心概念和实战技能。以下是根据...

    Java开发实战1200例(第1卷+第2卷)全代码

    《Java开发实战1200例(第1卷+第2卷)全代码》是一部全面覆盖Java编程实践的教程,旨在帮助开发者通过大量的实例来掌握Java语言的核心特性和实际应用。这部教程分为两卷,每卷都包含了丰富的编程示例,涵盖了从基础到...

    java8源码-baijia123:常用工具类及测试类

    第5章:基础构建模块 对应类包com.baijia123.concurrent TestHarnes-&gt;在计时测试中使用CountDownLatch(闭锁)来启动和停止线程 Preloader-&gt;使用FutureTask来提前加载稍后需要的数据 BoundedHashSet-&gt;使用Semaphore...

    Java入门到精髓实例版PPT

    第5章可能会讲解Java的输入/输出(I/O)系统,包括文件操作、流的概念和网络通信。这对于处理数据读写和构建服务器端应用非常重要。 第6章通常会涉及线程和并发编程,讲解如何在Java中创建和管理线程,以及如何使用...

    JAVA项目开发案例全程实录 第五章

    ### JAVA项目开发案例全程实录第五章:图书馆管理系统开发详解 #### 一、项目背景与需求分析 在《JAVA项目开发案例全程实录》第五章中,作者详细介绍了图书馆管理系统项目的开发过程。该项目旨在实现一个功能完备...

Global site tag (gtag.js) - Google Analytics