background image

Java 教程:多核平台下的 Java 优化

 

现在多核 CPU 是主流。利用多核技术,可以有效发挥硬件的能力,提升吞吐量,对于  
Java 

 

程序,可以实现并发垃圾收集。但是 Java 利用多核技术也带来了一些问题,主要是

 

多线程共享内存引起了。目前内存和 CPU 之间的带宽是一个主要瓶颈,每个核可以独享
一部分高速缓存,可以提高性能。JVM 

是利用操作系统的 轻量级进程 实现线程,所以线

程每操作一次共享内存,都无法在高速缓存中命中,是一次开销较大的系统调用。所以区
别于普通的优化,针对多核平台,需要进行一些特殊的优化。
  代码优化
  线程数要大于等于核数

 

  如果使用多线程,只有运行的线程数比核数大,才有可能榨干 CPU 资源,否则会有
若干核闲置。要注意的是,如果线程数目太多,就会占用过多内存,导致性能不升反降 。
JVM 

 

的垃圾回收也是需要线程的,所以这里的线程数包含 JVM 自己的线程

  尽量减少共享数据写操作
  每个线程有自己的工作内存,在这个区域内,系统可以毫无顾忌的优化,如果去读
共享内存区域,性能也不会下降。但是一旦线程想写共享内存(

 

使用 volatile 关键字),就

会插入很多内存屏障操作(Memory Barrier 

 

或者 Memory Fence)指令,保证处理器不

乱序执行。相比写本地线程自有的变量,性能下降很多。处理方法是尽量减少共享数据,

这样也符合 数据耦合 的设计原则。

 

  使用 synchronize 关键字

 

  在 Java1.5 中,synchronize 是性能低效的。因为这是一个重量级操作,需要调用

 

操作接口,导致有可能加锁消耗的系统时间比加锁以外的操作还多。相比之下使用 Java 

 

提供的 Lock 

 

对象,性能更高一些。但是到了 Java1.6,发生了变化。synchronize 在语

义上很清晰,可以进行很多优化,有适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等

 

等。导致在 Java1.6   

上 synchronize 

 

的性能并不比 Lock 差。官方也表示,他们也更支持 

synchronize,在未来的版本中还有优化余地。
  使用乐观策略
  传统的同步并发策略是悲观的。表现语义为:多线程操作一个对象的时候,总觉得会
有两个线程在同时操作,所以需要锁起来。乐观策略是,假设平时就一个线程访问,当出
现了冲突的时候,再重试。这样更高效一些。Java   

的 AtomicInteger 就是使用了这个策

略。
  使用线程本地变量(ThreadLocal)

 

  使用 ThreadLocal 可以生成线程本地对象的副本,不会和其他线程共享。当该线程
终止的时候,其本地变量可以全部回收。

 

  类中 Field 的排序

 

  可以将一个类会频繁访问到的几个 field 放在一起,这样他们就有更多的可能性被
一起加入高速缓存。同时最好把他们放在头部。基本变量和引用变量不要交错排放。
  批量处理数组