美文网首页Java并发编程实战-可爱猪猪解读
【连载】第2章-2.5活跃性与性能(缓存未必带来性能提升)

【连载】第2章-2.5活跃性与性能(缓存未必带来性能提升)

作者: 可爱猪猪 | 来源:发表于2019-08-23 16:33 被阅读0次

格言:在程序猿界混出点名堂!

已经连载了2个周,本书的第2章的解读也要结束了,下周可以开始第3章的解读,说实话,虽然很累,但是每天保持能够坚持读一个章节,慢慢寻味和体会,然后进行组织与总结,把书中最好的东西分享给大家。也是一种快乐。带给快乐的不仅是自己还有你们。另外需要看前面几期的解读,可以添加文章最下面的微信公众号。

《JAVA并发编程实战》解读
【连载】第2章-2.5活跃性与性能

回顾:上一节主要介绍了用锁来构造一种协议来保护共享状态的访问,也介绍了将对象的可变状态封装在对象的内部。这一节还是聊聊同步与活跃性和性能问题的一种微妙关系。

缓存未必带来性能提升

标题里面我们提到了缓存未必带来性能,既然这么说答案是值得深思的,前面章节的将上一次因数分解的计算结果缓存,以便下次可以直接读取缓存,提升性能,但为了保证缓存的lastNumber和lastFactors的原子操作,Servlet的方法上增加synchronized关键字,试想客户端必须串行来执行请求。这其实也违背了Servlet设计的初衷。这种并发称之为不良并发

不良并发.jpg

其实不难看出,是我们锁的粒度太粗,导致性能出现的问题。

减小锁粒度

@ThreadSafe
public class CacheFactorizer implements Servlet{
  @GuardedBy("this") private BigInteger lastNumber;
  @GuardedBy("this") private BigInteger lastFactors;
  @GuardedBy("this") private long hits;
  @GuardedBy("this") private long cacheHits;

  public void service(ServletRequest req,ServletResponse resp){
         BigInteger i = extractFromRequest(req);
         BigInteger factors = null;
         
         synchronized(this){
                hits++;
                if(i.equals(lastNumber)){
                      cacheHits ++;
                      factors = lastFactors.clone();       
                 }
         }
       
         if(factors == null){
              factors = factor(i) ;
              synchronized(this){
                  lastNumber = i;
                   lastFactors = factors;
              }
         }
  }

}

以上代码有几个看点:

  • 不难看出,以上程序减小的锁的粒度,将耗时比较长的factor(i),放在在锁的外边。
  • 为什么hits、cacheHits计数器不使用原子性的AtomicLong来替换呢?使用多种同步器不仅造成混乱,而且对性能提升也带来不了什么优势。
  • 为什么是 factors = lastFactors.clone(); 而不是 factors = lastFactors;?其实这里涉及到一个概念方法逃逸,即lastFactors从方法中逃逸出去,方法以外也能对该变量做修改,导致lastFactors不可控。

合理的同步代码块大小

要判断合理代码块的大小,就需要在安全性、简单性、性能之间平衡。

  • 安全性:即所见即所知,程序表现出的行为和状态期望一致。说白一点就是逻辑没毛病。这一点必须要保证,不能舍弃。
  • 简单性:往往满足简单性,牺牲的往往是性能。比如我们在方法上增加synchronized关键字,逻辑清晰简单。
  • 性能:在安全性保证的前提下,减小锁的粒度,用复杂性换取了性能。
    因此,在设计同步代码时,要在简单性和性能做出平衡选择。

耗时长的代码块不要使用锁

  • 造成线程都在等待,锁的等待时间太长,有可能导致事务未结束数据库连接池的链接占用不释放、微服务下的雪崩等。
  • 还有可能造成死锁,之前提到的银行转账死锁的例子,如果同步代码的时间过长,大大提升了死锁的概率。
    因此,耗时长的代码块,会带来性能和活跃性问题。

喜欢连载可关注简书或者微信公众号
简书专题:Java并发编程实战-可爱猪猪解读
https://www.jianshu.com/c/ac717321a386
微信公众号:可爱猪猪聊程序

相关文章

  • 【连载】第2章-2.5活跃性与性能(缓存未必带来性能提升)

    格言:在程序猿界混出点名堂! 已经连载了2个周,本书的第2章的解读也要结束了,下周可以开始第3章的解读,说实话,虽...

  • 转载:系统性能提升优先法宝 | 缓存应用实践

    转载:系统性能提升优先法宝 | 缓存应用实践 缓存是系统性能提升优先法宝,在互联网应用系统中,屡试不爽。网上有很多...

  • 搞懂Redis,这一篇就够了

    1、缓存带来的好处: 高性能 大量相同的请求过来,每次查询mysql耗时600ms,如果用缓存耗时20ms,性能提...

  • 网站架构

    提升系统性能 扩容 加缓存来提升系统并发能力 使用队列进行流量削峰 异步并发机制提升吞吐量或者接口性能 高并发原则...

  • 关于HTTP缓存

    缓存的目的: 重用已获取的资源能够有效的提升网站与应用的性能。Web 缓存能够减少延迟与网络阻塞,进而减少显示某个...

  • Spark 性能调优

    1 Spark SQL性能调优 通过缓存数据、调优参数、增加并行度提升性能P941)缓存数据构建一个内存中的列格式...

  • FMDB性能提升

    使用FMDB的过程中,性能的提升算一个技术点。 使用cache 既然是性能我们首先想到的是缓存cache缓存的话,...

  • 缓存中间件实践 - 缓存和数据库一致性更新原则

    1. 缓存和数据库一致性更新是什么? 1.1 缓存和数据库的关系 介绍 缓存:高性能产品 数据库:性能低产品 缓存...

  • HTTP之缓存

    缓存已获取的资源能够有效的提升网站与应用的性能,Web 缓存能够减少延迟与网络阻塞,进而减少显示某个资源所用的时间...

  • Web进阶 | 构建高可靠、高性能的Web应用

    功能 -> 性能✔ -> 智能 可靠性:可扩展性、服务降级、负载均衡、灰度性能:缓存、并发、池化、异步 一、可靠性...

网友评论

    本文标题:【连载】第2章-2.5活跃性与性能(缓存未必带来性能提升)

    本文链接:https://www.haomeiwen.com/subject/ilrasctx.html