Java并发编程实战-可爱猪猪解读

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

2019-08-23  本文已影响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;
              }
         }
  }

}

以上代码有几个看点:

合理的同步代码块大小

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

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

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

上一篇 下一篇

猜你喜欢

热点阅读