堆外并发计数器,并发计数器
堆外并发计数器,并发计数器
并发计数器几乎每个系统都有,它通常用来收集数据、实现线程同步。Java对于基于堆的计数器有很好的支持。
在某些情况下,需要建立多个进程共享的计数器。
如何建立进程间的计数器?
数据库
数据库是我们最容易想到的方法,数据库索引是一个可以被多进程共享的计数器。所有的并发都由数据库处理。对于初学者来说这是一个不错的选择,但是我们知道数据库会降低网络、锁等一些方面的性能。只有Larry Elision(译者注:Oracle的CEO)会对此感到高兴,你不会的。
服务器
你可以开发服务器或中间件提供这类服务,不过这种方法仍然会存在网络、序列化/反序列化方面的开销。
内存映射文件
你可以通过使用内存映射文件解决这一问题。我在听了PeterLawrey关于“Java中共享内存的进程间的线程安全”演讲之后想到了这个方法。
多进程计数器中遇到的困难
数据可视化
进程对数据的改变对于其他进程是可见的。这个问题可以通过使用内存映射文件解决,操作系统可以保证这一功能的实现,Java的内存模式也能支持这种方式。
线程安全
由于计数器有多个写入者,这使得线程安全成了一个很大的问题。比较与交换(Compare-and-swap,CAS)可以用来解决多个写入者的问题。但是,是否可以使用CAS实现堆外操作呢?答案是肯定的,欢迎使用Unsafe类。通过使用内存映射与Unsafe类结合可以使用CAS实现堆外操作。
在这篇博客中我将向大家分享我使用CAS实现内存映射的经验。
到底如何实现的?
怎样或得内存地址?
MappedByteBuffer使用DirectByteBuffer,其实是堆外内存。所以,我们可以获得内存的虚拟地址,并使用Unsafe类实现CAS操作。请看下面的代码:
FileChannel fc = new RandomAccessFile(fileName, "rw").getChannel(); // Map 8 bytes for long value. mem = fc.map(FileChannel.MapMode.READ_WRITE, 0, 8); startAddress = ((DirectBuffer) mem).address();
上面的代码创建了八字节的内存映射文件,同时获得了它的虚拟地址。这个地址可以用来读写内存映射文件中的内容。
如何实现线程安全的读写?
public boolean increment() { long orignalValue = readVolatile(startAddress); long value = convert(orignalValue); return UnsafeUtils.unsafe.compareAndSwapLong(null, startAddress,orignalValue, convert(value + 1)); } public long get() { long orignalValue = readVolatile(startAddress); return convert(orignalValue); } // Only unaligned is implemented private static long readVolatile(long position) { if (UnsafeUtils.unaligned()) { return UnsafeUtils.unsafe.getLongVolatile(null, position); } throw new UnsupportedOperationException(); } private static long convert(long a) { if (UnsafeUtils.unaligned()) { return (UnsafeUtils.nativeByteOrder ? a : Long.reverseBytes(a)); } throw new UnsupportedOperationException(); }
重点看一下readVolatile和increment函数,readVolatile直接从内存读取内容,increment 使用Unsafe类在MemoryByteBuffer得到的地址上实现CAS操作。
性能
下面是系统的性能参数。每个线程计数器统计一百万次。
计数器的性能在下降,随着线程数量的增加CAS操作的失败次数也开始增加,性能开始下降。这些计数器的性能可以通过资源分割减少资源来提高。我会在下一篇博文中详细介绍。
结论
- 内存映射文件十分有效,它可以用来开发一系列东西,如堆外集合、IPC、堆外线程同步等;
- 内存映射文件减少了垃圾回收GC的编程。
博客中的所有代码可以在github中下载。
译文链接: http://www.wld5.com/10905.html
[ 转载请保留原文出处、译者和译文链接。]
相关文章
- 暂无相关文章
用户点评