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

java并发编程实战-第11章-性能与可伸缩性

 
阅读更多

java并发编程实战-第11章-性能与可伸缩性

首先要保证程序的正确运行,仅当程序的性能需求和测试结果要求程序执行更快的时候,才应该设法提高程

 

序的运行速度

11.1 对性能的思考

要想通过并发提高性能,需要做好2件事:

更有效的利用现有的处理资源,以及在出现新的处理资源时使程序尽可能的利用新资源

如果是计算密集型的,则可以添加cpu来处理

 

11.1.1 性能与可伸缩性

本章重点介绍可伸缩性而不是单线程的性能

11.1.2 评估各种性能权衡因素

避免不成熟的优化。首先使城迅速正确,然后再提高运行速度

 

已测试为基准,不要猜测

 

11.2 Amdahl 定律

 

串行总是存在的,该定律告诉我们,为了提高程序的性能,加速比。需要降低程序中串行部分的比例

 

11.2.1 示例:在各种框架中隐藏的串行部分

 比较ConcurrentLinkedQueue 与synchronized Linked List

 

 随着线程数的增加,他们的吞吐率也会提高,但最后都会到达极限,不在增加

 

11.2.2 Amdahl 定律的应用

 

如果能准确估计出执行中串行部分所占在比分,则能量化当有多少资源时的加速比

 

在11.4.2 和11.4.3 节中,介绍的两种降低锁粒度的方法:锁分解和锁分段  。用Amdahl 定律分析,锁分

 

段更有前途,应为锁分段的数量可以随着处理器数量的增加而增加,串行的比例也会越来越低

 

11.3  线程引入的开销

11.3.1 上下文切换

 

    当线程由于锁而被阻塞时,jvm通常会把这个线程挂起,并允许它被交换出去。引起上下文切换,所以

 

仅从性能考虑,阻塞的地方越少越好,无阻塞算法(15章)有助于上下文切换

 

11.3.2 内存同步

 

   区分有竞争的同步和无竞争的同步非常重要。

   syncronized 针对无竞争的同步进行了优化。(volatile通常是非竞争的)

   不要过度担心非竞争同步带来的开销。应重点放在锁竞争的地方。

   

   

   无竞争的同步指加了同步修饰符(syncronized),但实际上该代码是无需同步的 。比如,方法内部对

 

变量的同步

   比如如下代码 Listing 11.3 :jvm会对同步进行锁消除优化:

   

    Listing 11.3. Candidate for Lock Elision.

public String getStoogeNames() {

   List<String> stooges = new Vector<String>();

   stooges.add("Moe");

   stooges.add("Larry");

   stooges.add("Curly");

   return stooges.toString();

}

  

  

    非竞争的同步可以完全在jvm中处理,而竞争的同步可能需要操作系统的介入,从而增加开销

   所以:重点关注:有竞争的同步

   

 

11.3.3 阻塞

   

      11.3.1 解释  上下文切换带来开销

   

 

11.4 减少锁的竞争

 

 

    串行操作降低可伸缩性,上下文切换降低性能。在锁上的竞争会同时发生如上两件事情,因此减少锁的

 

竞争能够提高性能和伸缩性

    

    

    在并发程序中,对可伸缩性最主要的威胁就是独占方式的资源锁

    

    有3种方式:

    1、减少锁的持有时间

    2、降低锁的请求频率

    3、使用带有协调机制的锁,这些机制允许更高的并发性

    

    

11.4.1 缩小锁的范围(“快进快出”)

       比如开发方法调用,改为同步方法内部的代码块

 

11.4.2 减少锁的粒度

      这可通过锁分解和锁分段技术来实现

      如果一个锁同时保护多个相互独立的状态变量,那么可以将这个锁分解为多个锁 。参考11.6到11.7

 

的转变

      

      Listing 11.6. Candidate for Lock Splitting.

@ThreadSafe

public class ServerStatus {

   @GuardedBy("this") public final Set<String> users;

   @GuardedBy("this") public final Set<String> queries;

   ...

   public synchronized void addUser(String u) { users.add(u); }

   public synchronized void addQuery(String q) { queries.add(q); }

   public synchronized void removeUser(String u) {

       users.remove(u);

   }

   public synchronized void removeQuery(String q) {

       queries.remove(q);

   }

}

 

 

Listing 11.7. ServerStatus Refactored to Use Split Locks.

@ThreadSafe

public class ServerStatus {

   @GuardedBy("users") public final Set<String> users;

   @GuardedBy("queries") public final Set<String> queries;

   ...

   public void addUser(String u) {

       synchronized  (users) { // 使用变量的锁,而不是ServerStatus的

 

           users.add(u);

       }

   }

 

   public void addQuery(String q) {

       synchronized  (queries) {//使用变量的锁,而不是ServerStatus的

 

           queries.add(q);

       }

   }

   // remove methods similarly refactored to use split locks

}

     

 

 

11.4.3 锁分段  

     ConcurrentHashMap   参靠list11-8

     

     Listing 11.8. Hash-based Map Using Lock Striping.

@ThreadSafe

public class StripedMap {

   // Synchronization policy: buckets[n] guarded by locks[n%N_LOCKS]

   private static final int N_LOCKS = 16;

   private final Node[] buckets;

   private final Object[] locks;

 

   private static class Node { ... }

 

   public StripedMap(int numBuckets) {

       buckets = new Node[numBuckets];

       locks = new Object[N_LOCKS];

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

           locks[i] = new Object();

   }

 

   private final int hash(Object key) {

       return Math.abs(key.hashCode() % buckets.length);

   }

 

   public Object get(Object key) {

       int hash = hash(key);

       synchronized (locks[hash % N_LOCKS]) {

           for (Node m = buckets[hash]; m != null; m = m.next)

               if (m.key.equals(key))

                   return m.value;

       }

       return null;

   }

 

   public void clear() {

       for (int i = 0; i < buckets.length; i++) {

           synchronized (locks[i % N_LOCKS]) {

               buckets[i] = null;

           }

       }

   }

   ...

}

11.4.4  避免热点域 

      一个看似性能优化的措施:缓存size操作的结果,会变成一个可伸缩性的问题。未避免这个问题,

 

ConcurrentHashMap为每个分段都维护了一个计数器,而不是一个全局的计数器。

      

11.4.5 一些替代独占锁的方法

 

  放弃独占锁,例如使用并发容器、读写锁、不可变对象以及原子变量

 

11. 4.6  监测cpu的利用率

 如果cpu未充分利用,通常有以下原因:

 负载不充足

 I/O 密集

 外部限制

 锁竞争

 

 

 如果cpu充分利用、并且总有可用的线程在等待cpu,那么当增加更多处理器的时候,程序性能可能会提提

 

 

 

 11.4.7 向对象池说不

       又是一个看似提高性能的措施,实际上会导致可伸缩性问题

       

       通常,对象的分配操作的开销比同步的开销要低

       

       

       

 11.5 比较Map的性能

 

    并发容器与同步容器

    单线程情况下,性能相当。2个线程,同步容器性能就变得糟糕了,而并发容器性能提高。线程继续增

 

加,竞争变得激烈,每个操作的时间大部分用于上下文切换和调度延迟,吞吐率不再提高

    

    

11.6 减少上下文切换的开销 

 

     以日志操作为例子,通过将io操作从处理请求分离出来,可以缩短服务的请求时间。调用log方法的线

 

程将不会因为等待输入输出流的锁或io完成而被阻塞。

     

     类似锁分解的方法,请求服务的锁和日志记录的锁从一个锁中分离出来。

     

     

小结:

  并发性能的重点通常是吞吐率和可伸缩性,而不是服务时间。Amdahl定律告诉告诉我们,程序的可伸缩性

 

取决于所有代码中串行执行的代码的比例。而java中串行操作的主要来源是独占方式的资源锁,因此可以通

 

过以下方式来提升性能

  :减少锁的持有时间、降低锁的粒度、采用非独占锁或非阻塞锁来代替独占锁

  

  

  

 

 

分享到:
评论

相关推荐

    62-Java并发编程实战

    62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java...

    java并发编程实战源码,java并发编程实战pdf,Java

    《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...

    Java并发编程实践-电子书

    Java并发编程实践-电子书-01章.pdf Java并发编程实践-电子书-02章.pdf Java并发编程实践-电子书-03章.pdf Java并发编程实践-电子书-04章.pdf Java并发编程实践-电子书-05章.pdf Java并发编程实践-电子书-06章.pdf ...

    Java 并发编程实战.pdf

    在《Java并发编程实战》中,读者也能够了解到如何将并发与现代Java语言特性结合起来,例如使用Lambda表达式和Stream API来简化并发代码的编写。 综合来看,该书不仅适合于对Java并发编程感兴趣的初学者,同样也适合...

    《java 并发编程实战高清PDF版》

    《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南。这本书旨在帮助开发者理解和掌握在Java环境中创建高效、可扩展且可靠的多线程应用程序的关键技术和实践。它涵盖了从基本概念到高级主题的广泛内容,...

    Java并发编程实战华章专业开发者书库 (Tim Peierls 等 美Brian Goetz).pdf

    《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南,由Tim Peierls等人与Brian Goetz合著,旨在帮助Java开发者理解和掌握在多线程环境中编写高效、安全的代码。这本书由拥有丰富经验的JDK并发大师及...

    Java 并发编程实战-随书源码

    《Java并发编程实战》这本书是Java开发者深入理解并发编程的重要参考书籍。本书旨在帮助程序员解决在多线程环境中遇到的实际问题,提升系统性能并保证其稳定性。随书源码提供了丰富的示例,让读者能够动手实践,加深...

    读书笔记-Java并发编程实战-基础篇

    在Java并发编程中,数据的封装与访问控制、线程安全性的考量、同步机制的使用是重要的基础概念和技巧。以下是从给出的文件内容中提取出的详细知识点: 1. 数据封装与访问控制:确保内部私有数据不被轻易访问,并且...

    (PDF带目录)《Java 并发编程实战》,java并发实战,并发

    《Java 并发编程实战》是一本专注于Java并发编程的权威指南,对于任何希望深入了解Java多线程和并发控制机制的开发者来说,都是不可或缺的参考资料。这本书深入浅出地介绍了如何在Java环境中有效地管理和控制并发...

    Java并发编程实践-电子书1-9章pdf

    9. **第九章:实战与性能调优** - 最后一章可能包括了实际并发编程中的最佳实践,性能测试和监控,以及如何根据系统需求进行性能调优。 以上只是基于常规并发编程书籍结构的猜测,具体内容还需要参考实际的电子书...

    Java并发编程实践-电子书-07章

    深入地探讨Java并发编程实践中的显示锁概念,我们聚焦于《Java并发编程实践-电子书-07章》所提供的丰富内容。本章着重于展示如何使用显示锁(也称为高级锁),并详细介绍了Lock和ReentrantLock接口以及它们在并发...

    JAVA并发编程实践-中文-高清-带书签-完整版

    《JAVA并发编程实践》是Java开发人员深入理解并发编程的一本经典著作,由Doug Lea撰写,本书中文版高清完整,包含丰富的书签,便于读者查阅和学习。这本书旨在帮助开发者掌握在Java平台上进行高效、安全并发编程的...

    Java 并发编程实战

    第11章 性能与可伸缩性 第12章 并发程序的测试 第四部分 高级主题 第13章 显式锁 第14章 构建自定义的同步工具 第15章 原子变量与非阻塞同步机制 第16章 Java内存模型 附录A 并发性标注

    Java并发编程实践-电子书-09章.pdf

    Java并发编程实践-电子书-09章.pdf

    Java并发编程---synchronized关键字

    Java并发编程---synchronized关键

    java并发编程实践pdf笔记

    Java并发编程实践是Java开发中不可或缺的一个领域,它涉及到如何高效、正确地处理多线程环境中的任务。这本书的读书笔记涵盖了多个关键知识点,旨在帮助读者深入理解Java并发编程的核心概念。 1. **线程和进程的...

Global site tag (gtag.js) - Google Analytics