您现在的位置是:首页 > 正文

java:CAS、ABA问题详解

2024-04-01 05:13:02阅读 3

1、java中的原子性操作

所谓原子性操作,是指执行一系列操作时,这些操作要么全部执行,要么全部不执行,不存在只执行其中一部分的情况。

2、CAS方法

CAS即Compare and Swap,其是JDK提供的非阻塞原子性操作,它通过硬件保证了比较-更新操作的原子性。CAS有四个操作数,分别为:对象内存地址、对象中的变量的偏移量、变量预期值和新的值。其操作含义为:如果对象obj中内存偏移量为valueOffset的变量为expect,则使用新的值update替换旧的值expect。也就是说,更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。这是处理器提供的一个原子性指令。

3、ABA问题

比如说一个线程one从内存位置V中取出A,这时候另一个线程two也从内存中取出A,并且two进行了一些操作变成了B,然后two又将V位置的数据变成A,这时候线程one进行CAS操作发现内存中仍然是A,然后one操作成功

尽管线程one的CAS操作成功,但是不代表这个过程就是没有问题的。

4、Unsafe类

getUnsafe方法源码:

    @CallerSensitive
    public static Unsafe getUnsafe() {
        Class<?> caller = Reflection.getCallerClass();
        if (!VM.isSystemDomainLoader(caller.getClassLoader()))
            throw new SecurityException("Unsafe");
        return theUnsafe;
    }
  • VM.isSystemDomainLoader(caller.getClassLoader()):这里判断是不是Bootstrap加载器加载了TestUnSafe.class。如果没有这个限制,那么我们的应用程序就可以随意使用Unsafe做事情了,而Unsafe类可以直接操作内存,这是不安全的,所以JDK开发组特意做了这个限制,不让开发人员再正规渠道使用Unsafe类,而是在rt.jar包里面的核心类中使用Unsafe功能。

我们可以使用万能的反射来获取Unsafe实例方法:

public class UnSafeTest2 {
    static final Unsafe unsafe;

    static final long stateOffset;

    private volatile long state = 0;

    static {
        try {
            // 使用反射获取Unsafe的成员变量theUnsafe
            Field field = Unsafe.class.getDeclaredField("theUnsafe");

            // 设置为可存取
            field.setAccessible(true);

            // 获取该变量的值
            unsafe = (Unsafe) field.get(null);

            // 获取state在UnsafeTest2中的偏移量
            stateOffset = unsafe.objectFieldOffset(UnSafeTest2.class.getDeclaredField("state"));
        }catch (Exception e) {
            System.out.println(e.getLocalizedMessage());
            throw new Error(e);
        }
    }

    public static void main(String[] args) {
        UnSafeTest2 test2 = new UnSafeTest2();
        Boolean flag = unsafe.compareAndSwapInt(test2, stateOffset, 0, 1);
        System.out.println(flag);
    }
}

 

网站文章

  • 系统错误:&amp;H8007007E(-2147024770)。 找不到指定的模块。解决

    系统错误:&amp;H8007007E(-2147024770)。 找不到指定的模块。 就很发呆,以前就正常。 然后发现多个ocx,那肯定是这个组件没有注册了。运行了vb库失败后,便从程序里复制了MSINET.OCX,放到了c:/windows/systems32 下面 然后在开始运行里输入:regsvr32 MSINET.OCX,进行注册 提示注册成功后,完成 程序...

    2024-04-01 05:12:20
  • layui踩坑记录之form表单下的button按钮默认自动提交

    layui踩坑记录之form表单下的button按钮默认自动提交

    因此,当我们在使用form的时候,如果没有添加标准的提交按钮,会自动默认把其他的普通按钮认为是提交按钮,因为button的type默认值为“submit”。其实就是使用form的时候,应该对应有一个提...

    2024-04-01 05:12:12
  • 加快局域网访问时间的方法策略

    法一:将网卡调至全速按下Win+Pause/Break键,单击“硬件”标签,再单击“设备管理器”从而打开“设备管理器”,双击“网络适合器”下相应网卡,在打开窗口中单击“高级”标签,选中Link Spe...

    2024-04-01 05:12:06
  • 微信小程序-处理多个文件上传

    一、方法的封装/** * 采用递归的方式上传多个文件 * filePaths 要上传的资源 * results 上传成功返回的数据 * successUp 成功个数 * failUp 失败个数 * index 上传文件的下标 */function uploadOneByOne(filePaths = [], results = [] , successUp =...

    2024-04-01 05:11:59
  • SQL过滤与应用过滤如何选择

    SQL过滤与应用过滤进行复杂查询的时候,数据可以通过SQL过滤,也可以在应用层进行过滤。应当优先采用哪一种过滤方式呢?通常来说,优化数据库后可以更快速有效的对数据进行过滤。使用客户端进行过滤的方法通常是:sql的select语句为客户端应用检索出超过实际所需的数据,然后客户端代码对返回数据进行循环提取出需要的行。使用客户端应用进行过滤时,有三个不好的影响:1.会极大的影响应用的性能2....

    2024-04-01 05:11:19
  • 系统管理员设置了系统策略禁止此安装怎么办

    系统管理员设置了系统策略禁止此安装怎么办

    解决措施

    2024-04-01 05:11:11
  • vue项目开发全局组件笔记

    在开发vue项目时,经常会用到element UI组件,在全局使用像message,toast,alert等组件得时候会很方便,但是在开发需要UI制定的项目时,就不能使用element UI了,这时就需要自己去开发属于自己的组件库了。具体的开发方法官网提供了。下面我们就根据官网提供的方法来开发属于我们自己的alert警告组件首先我们要在src/components文件夹下创建一个alert文...

    2024-04-01 05:11:04
  • 服务器有新消息主动推送给客户端浏览器

    服务器有新消息主动推送给客户端浏览器

    前言 通常情况下,无论是web浏览器还是移动app,我们与服务器之间的交互都是主动的,客户端向服务器端发出请求,然后服务器端返回数据给客户端,客户端浏览器再将信息呈现,客户端与服务端对应的模式是: 客...

    2024-04-01 05:10:23
  • 算法入门之排序算法

    算法入门之排序算法

    算法入门之排序算法堆排序堆排序相较于堆排序这种排序算法,堆这种数据结构更为重要/** * @Author Jason * @Date 2021/9/11 11:09 上午 * @Description...

    2024-04-01 05:10:14
  • android绑定Service失败原因

    今天抄一个代码,学习Service,中间Service的绑定一直是失败的。bindService返回false上网查询的话都是一些,比如说TabHost的问题发现和自己的问题不一样。最后想了想,原来是AndroidManifest.xml这个文件没有改,要添加一个Service的段哎,低级错误害人害己 转载请注明来自:http://blog.csdn.net/icyfo...

    2024-04-01 05:10:07