并发中的Native方法,CAS操作与ABA问题

简介:

1.JNI和Native方法

Java中,通过JNI(Java Native Interface,java本地接口)来实现本地化,访问操作系统底层,如系统硬件等。

JNI的实现就是在Java里声明方法,然后编写C/C++实现该方法,步骤:

  • 编写带有native声明的方法的java类,得到.java文件
  • 使用javac命令编译所编写的java类,生成.class文件
  • 使用javah -jni java类名生成扩展名为h的头文件,也即生成.h文件
  • 使用C/C++(或者其他编程想语言)实现本地方法,创建.h文件的实现,也就是创建.cpp文件实现.h文件中的方法
  • 将C/C++编写的文件生成动态连接库,生成dll文件
  • 在Java中用System.loadLibrary()方法加载上面生成的动态链接库文件,这个native()方法就可以在Java中被访问了

在《java核心技术》中,建议不到万不得已不要使用JNI技术,一方面它需要你掌握更多的知识才可以驾驭,一方面使用了JNI你 的程序就会丧失可移植性。

2.sun.misc.Unsafe

Java无法直接访问底层操作系统,而是通过本地(native)方法来访问。JDK中有一个类sun.misc.Unsafe,它提供了硬件级别的原子操作。

在Java.util.concurrent包里的很多代码实现都可以看到它的踪影。这个类尽管里面的方法都是public的,但是开发者是无法使用它的,只有在JDK内部实现中可以看到调用。

3.乐观锁和悲观锁

独占锁:是一种悲观锁,synchronized就是一种独占锁,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。
乐观锁:每次不加锁,假设没有冲突去完成某项操作,如果因为冲突失败就重试,直到成功为止。
乐观锁用到的机制就是CAS,Compare and Swap。
CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

4.CAS操作

CAS,Compare and Swap即比较并替换,设计并发算法时常用到的一种技术,
java.util.concurrent包很多地方都是使用的CSA,CAS是并发设计中非常重要。

CAS有三个操作数:

内存值V、旧的预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做并返回false。

当前的处理器基本都支持CAS,只不过不同的厂家的实现不一样。

以AtomicInteger为例,研究在没有锁的情况下是如何做到数据正确性的

1
private  volatile  int  value;

在没有锁的机制下需要借助volatile原语,在主存中直接操作,保证线程间的数据是共享的,
这样才获取变量的值的时候才能直接读取。

1
2
3
4
public  final  int  get() {
//因为使用了volatile所以可以直接读取
return  value;
}

然后来看看 ++i 是怎么做到的,代码来自JDK1.6:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
     * Atomically increments by one the current value.
     *
     * @return the previous value
     */
    public  final  int  getAndIncrement() {
        for  (;;) {
            int  current = get();
            int  next = current +  1 ;
            if  (compareAndSet(current, next))
                return  current;
        }
    }

 

在这里采用了CAS操作,每次从内存中读取数据然后将此数据和+1后的结果进行CAS操作,如果成功就返回结果,否则重试直到成功为止。

而compareAndSet利用JNI来完成CPU指令的操作

1
2
3
4
5
6
7
/**
      * Atomically sets the value to the given updated value
      * if the current value {@code ==} the expected value.
      */
     public  final  boolean  weakCompareAndSet( int  expect,  int  update) {
         return  unsafe.compareAndSwapInt( this , valueOffset, expect, update);
     }

整体的过程就是这样子的,利用CPU的CAS指令,同时借助JNI来完成Java的非阻塞算法

concurrent包下的原子类型都是这么实现的。

5.ABA问题

CAS:对于内存中的某一个值V,提供一个旧值A和一个新值B。如果提供的旧值V和A相等就把B写入V。这个过程是原子性的。
CAS执行结果要么成功要么失败,对于失败的情形下一班采用不断重试。或者放弃。
ABA:如果另一个线程修改V值假设原来是A,先修改成B,再修改回成A。当前线程的CAS操作无法分辨当前V值是否发生过变化。

如何解决ABA问题?



本文转自邴越博客园博客,原文链接:http://www.cnblogs.com/binyue/p/3436999.html,如需转载请自行联系原作者

相关文章
|
数据采集 安全 Windows
解决关于Windows Defender Antivirus Service自启造成运行python程序时,Windows的cpu和内存占用过高问题
启用“关闭Windwos defender”服务解决阿里云Windows服务器的卡顿问题,并列举了网上一些错误的解决方法。
13009 3
解决关于Windows Defender Antivirus Service自启造成运行python程序时,Windows的cpu和内存占用过高问题
|
Docker 容器
Docker——Centos8.2安装Docker
Docker——Centos8.2安装Docker
242 0
|
11月前
|
存储 物联网 数据安全/隐私保护
Docker安装Mosquitto
这篇文章详细介绍了如何在Docker中安装和配置Mosquitto消息代理服务,包括拉取镜像、创建容器以及配置持久化存储等步骤。
968 0
Docker安装Mosquitto
|
算法 Linux Windows
linux中的压缩软件介绍
这些是Linux中一些常见的压缩软件工具,您可以根据需要选择合适的工具来压缩和解压缩文件。每种工具都有其特定的特点和压缩性能,因此根据具体情况选择合适的工具是重要的。
269 0
|
安全 搜索推荐 Linux
D-Bus深度解析:系统总线与会话总线的区别与应用
D-Bus深度解析:系统总线与会话总线的区别与应用
504 2
Element UI【级联选择器】el-cascader 获取选中内容的 label 数据,鼠标悬浮显示超长内容
Element UI【级联选择器】el-cascader 获取选中内容的 label 数据,鼠标悬浮显示超长内容
1472 3
|
机器学习/深度学习 算法 TensorFlow
【深度学习】基于卷积神经网络(tensorflow)的人脸识别项目(一)
【深度学习】基于卷积神经网络(tensorflow)的人脸识别项目(一)
465 0
【深度学习】基于卷积神经网络(tensorflow)的人脸识别项目(一)
|
监控 Unix Linux
C语言进程(第一章进程基础,fork()函数,pid_t, pid, getpid())
C语言进程(第一章进程基础,fork()函数,pid_t, pid, getpid())
700 0
|
缓存 小程序 NoSQL
【Uniapp】小程序携带Token请求接口+无感知登录方案
【Uniapp】小程序携带Token请求接口+无感知登录方案
471 0
|
Java API
Java8特性第四讲:Java 8的接口默认方法实现
Java8特性第四讲:Java 8的接口默认方法实现
360 0