笔记_并发编程实践_十一

性能和可伸缩性

 

1.可伸缩性:

<1>可伸缩性是指:当增加计算机资源的时候(增加额外的cpu数量,内存,存储器,I/O带宽),吞吐量和生产性能得到相应的提高。(吞吐量是指在单位时间内中央处

理器(CPU)从存储设备读取->处理->存储信息的量。)

<2>使用工具来衡量是优化的效果,如免费的perfbar能够告诉你cpu的忙碌状况,可用 于衡量是否能使cpu得到充分的利用

 

2.amdahl定律

<1>我们必须保证任务并恰当的并行分解(如有些任务是必须串行之行的,就不能并 发。)

<2>amdahl定律描述了在相应的串行组件比重下,计算机资源的增加理论上能获得的性 能提高,n是处理器数,f是串行组件占系统组件的比重:

speedUp<=1/(F+(1-F)/N)

 

3.线程引入的开销

<1>上下文切换:当前线程数大于可用cpu数,os会强行切换正在执行的线程。而一个 线程在刚开始调度时由于所需的数据不一定缓存在当前本地处理器中,导致线程一开始 调度时比较慢,产生上下文切换的开销

<2>内存同步:

1】如synchroniedvolatile等由于需要确保可见性,需要和内存总线交互,抑制 编译器优化,并且会占用总线的带宽。

2】区分竞争同步和非竞争同步,volatile是竞争同步,基础机制保证了它的速度 足够快,而synchronized对于无竞争同步也有相应优化(书中的这部分有点模糊, 估计是,synchronized是有竞争的同步,但是即使加了锁也可能存在一些状况,在 该状况下该锁并没有其他线程竞争,就是所谓的‘无竞争同步’,不同于‘非竞争 同步’,而在无竞争同步上,jvm会对其优化,使得取消对锁的操作,减少开销)

 

4.阻塞

<1>当线程竞争锁失败后,jvm既可以自旋等待(不断询问知道锁可用)又可以挂起线 程,大部分是挂起线程,当线程被挂起到适当时间后重新启用需要两次的上下文切换, 并且会导致os操作

 

5.减少锁的竞争

<1>注意一点,串行化会减弱可伸缩性(吞吐量等),多线程带来的上下文切换也会损 耗性能

<2>并发程序中,对伸缩性影响最大的是独占的资源锁(入某些共享资源只允许串行访 问?)

<3>影响锁竞争性的两个条件:【1】锁被请求的频率,【2】持有锁的时长

<4>减少竞争:【1】降低请求锁的频率,【2】降低持有锁的时长,【3】协调机制取代独 占锁

<5>缩小锁的范围。减少synchronied代码块的大小,即有些无需同步的操作不放在代码 块中(尤其是比 较耗时的)

<6>减少锁的粒度:

(1)可通过分拆锁和分离锁实现

(2)如果锁中包含多个状态变量,并且这些变量间相互独立,并且这些锁不会被激烈竞争时,则可以采用每个共享变量都用一个锁去同步的方式,而不是全部用一个锁,这样可以降低争用(但是会增加死锁的风险),即分离锁。

(3)分拆锁可以被扩展,分拆成可大可小的锁块的集合,并且他们归属于相互独立的对象,这样的情况就是分离锁

(4)concurrenthashmap的实现体现分离锁的原理:它实现了一个拥有16个锁对象的array,每一个锁都守护hashbucket的1/16,假设哈希提供合理的扩特性,并且关键字能够以统一的方式访问,可以把锁的竞争降低到原来的1/16,这一算法是的ConcurrentHashMap可支持16个并发的writer(当争用强度足够强大时,你可以增大锁的数量)(hash bucket 哈希桶,是实现哈希表解决冲突的一种方式)

(5)分离锁的缺点:由于对容器个部分加锁,当需要独占访问整个容器时,更困难,代价更昂贵


6.避免热点域

(1)那些对锁的竞争大于对数据的竞争才适合使用分离锁和分拆锁(例如访问两块不同的数据,但只使用一个锁的情况适合分离锁或分拆锁,但当访问的是同一块数据是不然)

(2)热点域:如concurrenthashmap的size(),若然需要获Map得大小,在并发环境下必须维护一个计数器,并且同步访问,则上述分离锁即使能把对各部分的数据的操作分离,也必须在每一次操作某数据时对整个map的size计数器的相应操作同步,像这样一个需要被各部分同步访问的计数器就是热点域。(currenthashmap的解决办法时分16个计数器,在size()时把各个计数器枚举)。

7.独占锁的替代方法

(1).对于只读数据,不可变性可以完全消除加锁的必要

(2).如果你的类只有少量热点域,并且该类不参与其他变量的不变约束,那么使用原子变量替代它可以提高可伸缩性(原子变量减少更新热点域的开销)

8.检测cpu的利用率

(1)我们的目标通常是保持处理器的充分利用

(2)unix系统的vmstat和mpstat,或者windows系统的perfmon都能告诉你处理器有多忙碌

(3)如果所有的cpu没有被均衡地利用,那么你的首要目标应该是增加你的程序的并行性,可能由以下原因导致cpu的不均衡被利用:

<1>不充足的负载,可能被测试程序没有加入足够多的负载,可检查利用率,响应时间,服务器的运行时间的变化。(有可能是客户端没有足够的能力,二不是被测试系统)

<2>i/o限制。可以通过iostat或者perfmon判断是否受限于磁盘或者检测他的网络通信量判断它是否有带宽限制

<3>外部限制,如果你的应用程序取决于外部服务,比如数据库,或者webservice,那么瓶颈肯能不在于你自己的代码,可以用过使用profiler工具或者数据库管理工具来判断等待外部服务结果的用时。

<4>锁竞争,可以通过剖析器(profiler)或者线程转存来获得锁的争用信息(如线程转存中获得当前那些线程在等待那些锁,可以看出等待那些锁是否频繁)

9.向‘对象池’说不:随着jvm垃圾回收和对象分配性能的提高,使用对象池来分配对象需要的同步开销元高于分配一个对象,可能会导致性能的瓶颈(对象池技术通常是有其他用途,但是对于性能优化来说是有局限性的。)


10.减少上下文切换的开销

(1)很多任务引入的操作都会发生阻塞,在运行和阻塞这两个状态之间转换需要使用上下文切换

(2)书中以日志的例子体现,当采用多线程的日志输出,对io等的竞争会导致上下文的切换开销,该为使用当线程输出,所有的日志加入日志对鞋,而单一的线程在日志队列中存在元素时就取出并输出,减少io竞争。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值