信息化 频道

面向多核处理器实现高性能中间件

    3、协同中间件并发性能提升实践

    协同对其中间件产品升级过程中大量应用了JSR-166所提供的类库和并发功能,并基于其开发了更高层次的类库,获得了深刻的应用经验,下面将就此进行讨论,以期抛砖引玉。

    3.1使用原子变量

    通常在中间件产品的实现中,有很多情况需要实现多线程使用的计数器或随机数生成器作为ID,这时一般会使用锁来保护共享变量。这样会使得多线程对锁竞争,造成大量线程处于等待状态,浪费了cpu资源,损害了吞吐量。

    volatile 变量虽然可以使用比同步更低的成本存储共享变量,但它只可以保证其他线程能够立即看到对 volatile 变量的写入,无法保证读-修改-写的原子性。因此,volatile 变量无法用来实现正确的计数器和随机数生成器。

    在这种情况下,可以利用JSR-166包中的原子变量,实现更高效的计数器和随机数生成器。这些原子变量包括 AtomicInteger、AtomicLong、AtomicBoolean 以及数组 AtomicIntergerArray、AtomicLongArray等类型。

    下面是计数器的传统实现:

    public final class Counter {

    private long value = 0;

    public synchronized long getValue() {

    return value ++;

    }

    }

    下面则是采用原子变量实现的计数器:

    public final class Counter {

    private AtomicLong value = 0;

    public long getValue() {

    return value. getAndIncrement();

    }

    }

    3.2使用并发数据结构

    Collection 框架曾为 Java 程序员带来了很多方便,但在多核时代,Collection 框架变得有些不大适应。多线程之间的共享数据总是存放在数据结构之中,如 Map、Stack、Queue、List、Set 等。 Collection 框架中的这些数据结构在默认情况下并不是多线程安全的,也就是说这些数据结构并不能安全地被多个线程同时访问。 JDK 通过提供 SynchronizedCollection 为这些类提供一层线程安全的接口,它是用 synchronized 关键字实现的,相当于为整个数据结构加上一把全局锁保证线程安全。

    JSR-166中提供了更加高效 collection,如 ConcurrentHashMap/Set, ConcurrentLinkedQueue, ConcurrentSkipListMap/Set, CopyOnWriteArrayList/Set .这些数据结构是为多线程并发访问而设计的,使用了细粒度的锁和新的 Lock-free 算法。除了在多线程条件下具有更高的性能,还提供了如 put-if-absent 这样适合并发应用的原子函数。

    使用并发数据结构的优势:

    使用者不需要锁

    并发性能优异,特别适合多核多线程应用

    在并发情况下,更容易使用,不容易出错
 

0
相关文章