Unsafe介绍以及几种Counter方案性能对比
2019-04-16 本文已影响0人
yincb
一 、Unsafe介绍
1.1 作用
可以用来在任意内存地址位置处读写数据,支持一些CAS原子操作
Java最初被设计为一种安全的受控环境。尽管如此,HotSpot还是包含了一个后门sun.misc.Unsafe,提供了一些可以直接操控内存和线程的底层操作。Unsafe被JDK广泛应用于java.nio和并发包等实现中,这个不安全的类提供了一个观察HotSpot JVM内部结构并且可以对其进行修改,但是不建议在生产环境中使用
1.2 获取Unsafe实例
Unsafe对象不能直接通过new Unsafe()或调用Unsafe.getUnsafe()获取,
原因如下:
不能直接new Unsafe(),原因是Unsafe被设计成单例模式,构造方法是私有的;
不能通过调用Unsafe.getUnsafe()获取,因为getUnsafe被设计成只能从引导类加载器(bootstrap class loader)加载
private static Unsafe getUnsfe(){
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
二、几种Counter方案性能对比
public class UnsafeTest {
public static void main(String[] args) throws Exception {
ExecutorService service = Executors.newFixedThreadPool(1000);
/**
* StupiedCounter
* counter:9955671
* time:334
*/
//Counter counter = new StupiedCounter();
/**
* SyncCounter
* counter:10000000
* time:1878
*/
//Counter counter = new SyncCounter();
/**
* LockCounter
* counter:10000000
* time:413
*/
// Counter counter = new LockCounter();
/**
* AtomicCounter
* counter:10000000
* time:287
*/
// Counter counter = new AtomicCounter();
/**
* CasCounter
* counter:10000000
* time:638
*/
Counter counter = new CasCounter();
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
service.submit(new CounterRunner(counter,10000));
}
service.shutdown();
service.awaitTermination(1, TimeUnit.HOURS);
long end = System.currentTimeMillis();
System.out.println("counter:"+counter.getCounter());
System.out.println("time:"+(end-start));
}
private static Unsafe getUnsfe(){
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static class StupiedCounter implements Counter{
private long counter = 0;
@Override
public void increment() {
counter++;
}
@Override
public long getCounter() {
return counter;
}
}
static class SyncCounter implements Counter{
private long counter = 0;
@Override
public synchronized void increment() {
counter++;
}
@Override
public long getCounter() {
return counter;
}
}
static class LockCounter implements Counter{
private long counter = 0;
private Lock lock = new ReentrantLock();
@Override
public void increment() {
try {
lock.lock();
counter++;
}finally {
lock.unlock();
}
}
@Override
public long getCounter() {
return counter;
}
}
static class AtomicCounter implements Counter{
private AtomicLong counter = new AtomicLong();
@Override
public void increment() {
counter.incrementAndGet();
}
@Override
public long getCounter() {
return counter.get();
}
}
static class CasCounter implements Counter{
private long counter = 0;
private Unsafe unsafe;
private long offset;
public CasCounter() throws NoSuchFieldException {
this.unsafe = getUnsfe();
this.offset = unsafe.objectFieldOffset(CasCounter.class.getDeclaredField("counter"));
}
@Override
public void increment() {
long current = counter;
while (!unsafe.compareAndSwapLong(this,offset,current,current+1)){
current = counter;
}
}
@Override
public long getCounter() {
return counter;
}
}
interface Counter{
void increment();
long getCounter();
}
static class CounterRunner implements Runnable{
private final Counter counter;
private final int num;
CounterRunner(Counter counter, int num) {
this.counter = counter;
this.num = num;
}
@Override
public void run() {
for (int i = 0; i < num; i++) {
counter.increment();
}
}
}
}