这很Unsafe-非锁算法

上一篇从并发模型Master-Worker说起提到了CAS和Unsafe。
这一篇是一次实践,通过模仿(盗版)AtomicInteger来形成线程安全类编写的思想。当然,这只是一次教学,真正项目中,慎用。
先给出编写好的MyAtomicInteger源码,这个就是盗版AtomicInteger的。只有些许变化。

package com.chen.cas;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * Created by CHEN on 2016/9/28.
 *
 * 这是一次对AtomicInteger的盗版
 */
public class MyAtomicInteger {

    private static final sun.misc.Unsafe UNSAFE;
    private static final long valueOffset;

    private volatile int value;//可视的值
    static {
        try {
            //请看这个方法解释
            UNSAFE = MyAtomicInteger.getUnsafe();//sun.misc.Unsafe.getUnsafe();
            Class<?> k = MyAtomicInteger.class;//当前类
            valueOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("value"));//对应可视的值
        } catch (Exception e) {
            throw new Error(e);
        }
    }

    /**
     * 初始化
     * @param initalValue
     */
    public MyAtomicInteger(int initalValue) {
        this.value = initalValue;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    //传入增长的幅度
    public final int addAndGet(int delta) {
        //调用Unsafe的native方法
        return UNSAFE.getAndAddInt(this,valueOffset,delta);
    }

    /**
     * 这个方法是和AtomicInteger唯一的区别
     * sun.misc.Unsafe这个类是如此地不安全,
     * 以至于JDK开发者增加了很多特殊限制来访问它。
     * 它的构造器是私有的,
     * 工厂方法getUnsafe()的调用器只能被Bootloader加载。
     * 如你在下面代码片段的第8行所见,
     * 这个家伙甚至没有被任何类加载器加载,
     * 所以它的类加载器是null。
     * 它会抛出SecurityException 异常来阻止侵入者。
     *
     * 因此 我们只能通过反射来获得。
     * @return
     */
    public static Unsafe getUnsafe() {
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            return (Unsafe)f.get(null);
        } catch (Exception e) {
            return null;
        }
    }

    //重写toString
    public String toString() {
        return Integer.toString(getValue());
    }
}

测试类

package com.chen.cas;

/**
 * Created by CHEN on 2016/9/28.
 */
public class Application {
    public volatile static MyAtomicInteger NUM = new MyAtomicInteger(0);
    //public volatile static AtomicInteger NUM = new AtomicInteger(0);

    public static void main(String[] args) {
        //String s = "";
        for (int i = 0; i <= 1000; i++) {
            Thread thread=new Thread(() -> {
                try {
                    // synchronized (s) {
                    Thread.sleep(10);
                    Application.NUM.addAndGet(1);
                    System.out.println(Application.NUM);

                    // }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            thread.start();
        }
        try {
            Thread.sleep(1000);//此处不能用join,因为没有命名
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("值为" + Application.NUM);
    }
}

以上就是怎么写一个线程安全共享对象的例子。以此类推,也可以写成更多的方法。Unsafe下提供了很多的native方法,都是靠底层代码,信号量进行隔离操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值