基于sun.misc.Unsafe 开发自己的非阻塞线性安全的类

版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在页面明显位置给出原文链接。 https://blog.csdn.net/mengxiangqihangz/article/details/84311920

非阻塞 线性安全的类

import sun.misc.Unsafe;
import com.base.Unsafe.UnsafeUtil;
/**
 *  利用cas算法 将 SafeEntity 设计成 一个 非阻塞 线性安全的类
 * 并非完全的非阻塞,而是通过原子级操作,避免了加锁和释放锁。
 * unsafe.compareAndSwapInt(this, nextOffset, now, after); 就是一个原子操作。一次只能一个线程通过。
 * cas算法:全称 compare and set ,就是set之前先对比,是否等于预期值,等于预期值就set一个新的值,返回ture,
 * 																否则返回false
 * compareAndSet() 中有一个递归调用,保证了每一次 改变 都能够成功。
 * @author liangpro
 *
 */
public class SafeEntity {
	private int num;
	private int sum;
	
	public void numAddOne() throws Exception {
		final Unsafe unsafe = UnsafeUtil.getUnsafeInstance();
		long nextOffset = 0l;
		long nextOffsetSum = 0l;
		try {
			nextOffset = unsafe.objectFieldOffset(SafeEntity.class.getDeclaredField("num"));//获取SafeEntity类的num属性的 内存偏移量。
			nextOffsetSum = unsafe.objectFieldOffset(SafeEntity.class.getDeclaredField("sum"));
		} catch (NoSuchFieldException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		compareAndSet(unsafe, nextOffset);
		//doSomeThing();
		compareAndSetSum(unsafe, nextOffsetSum);
	}
	
	public boolean compareAndSet(Unsafe unsafe,long nextOffset){
		int now = this.num;
		int after = now +1;
		boolean flag =  unsafe.compareAndSwapInt(this, nextOffset, now, after);//若this的内存偏移 nextOffset处的值为 now,则更新为 after
		if(!flag){
			compareAndSet(unsafe, nextOffset);//如果不成功,则再尝试修改一次。
		}
		return flag;
	}
	public boolean compareAndSetSum(Unsafe unsafe,long nextOffset){//可以为每一个线性不安全的操作,引入原子级修改操作。使整个类达到线程安全。
		int now = this.sum;
		int after = now + 2;
		boolean flag =  unsafe.compareAndSwapInt(this, nextOffset, now, after);
		if(!flag){
			compareAndSetSum(unsafe, nextOffset);
		}
		return flag;
	}

	public int getNum() {
		return num;
	}
	public int getSum() {
		return sum;
	}
}

test类

import java.util.concurrent.CountDownLatch;
public class UnsafeTest {
	public static int num;
	public static CountDownLatch latch = new CountDownLatch(50);
	
	public static void main(String[] args) throws InterruptedException {
		SafeEntity safe = new SafeEntity();
		for (int i = 0; i < 50; i++) {
			new ThreadDemo(safe,latch).start();
		}
		latch.await();
		System.out.println(safe.getNum());
		System.out.println(safe.getSum());
	}
	
	static class ThreadDemo extends Thread{
		SafeEntity safe;
		CountDownLatch latch;
		public ThreadDemo(SafeEntity safe,CountDownLatch latch){
			this.safe = safe;
			this.latch = latch;
		}
		
		public void run(){
			for (int i = 0; i < 100000; i++) {
				try {
					safe.numAddOne();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			latch.countDown();
		}
	}
}

获得sun.misc.Unsafe实例的工具类

import java.lang.reflect.Field;
import sun.misc.Unsafe;

// 方法一:我们可以令我们的代码“受信任”。运行程序时,使用bootclasspath选项,指定系统类路径加上你使用的一个Unsafe路径
//java -Xbootclasspath:/usr/jdk1.7.0/jre/lib/rt.jar:. com.mishadoff.magic.UnsafeClient

public class UnsafeUtil {
	
	public static Unsafe getUnsafeInstance() throws SecurityException,
			NoSuchFieldException, IllegalArgumentException,
			IllegalAccessException {
		Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
		theUnsafeInstance.setAccessible(true);
		return (Unsafe) theUnsafeInstance.get(Unsafe.class);
	}
	
	public static Unsafe getUnsafe() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
		Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        return (Unsafe) field.get(null);
	}
	
}

猜你喜欢

转载自blog.csdn.net/mengxiangqihangz/article/details/84311920