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

Native方法,Unsafe与CAS操作

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值是否发生过变化。


时间: 2025-01-01 15:20:03

并发中的Native方法,CAS操作与ABA问题的相关文章

JAVA并发编程学习笔记之CAS操作

CAS操作 CAS是单词compare and set的缩写,意思是指在set之前先比较该值有没有变化,只有在没变的情况下才对其赋值. 我们常常做这样的操作 if(a==b) { a++; } 试想一下如果在做a++之前a的值被改变了怎么办?a++还执行吗?出现该问题的原因是在多线程环境下,a的值处于一种不定的状态.采用锁可以解决此类问题,但CAS也可以解决,而且可以不加锁. int expect = a; if(a.compareAndSet(expect,a+1)) { doSomeThin

转 Java中的native关键字

一.  什么是Native Method    简单地讲,一个Native Method就是一个java调用非java代码的接口.一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C.这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数.    "A native method is a Java method whose implementati

使用native方法扩展Java程序的功能详解

Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能. 可以将native方法比作Java程序同C程序的接口,其实现步骤: 1.在Java中声明native()方法,然后编译: 2.用javah产生一个.h文件: 3.写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件): 4.将第三步的.cp

让JavaScript中setTimeout支持链式操作的方法

  这篇文章主要介绍了让JavaScript中setTimeout支持链式操作的方法,本文直接给出代码实例,需要的朋友可以参考下 修改很简单,通过参数判断,然后返回下promise对象 代码如下: (function() { var timeout = setTimeout; window.setTimeout = function(fn, time) { if (!time) { time = fn; return $.Deferred(function(dfd) { timeout(func

javascript操作ul中li的方法

  本文实例讲述了javascript操作ul中li的方法.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 <!DOCTYPE html PUBLIC "-//W3C//DT

在Python中使用next()方法操作文件

  这篇文章主要介绍了在Python中使用next()方法操作文件的教程,是Python入门中的基础知识,需要的朋友可以参考下 next()方法当一个文件被用作迭代器,典型例子是在一个循环中被使用,next()方法被反复调用.此方法返回下一个输入行,或引发StopIteration异常EOF时被命中. 与其它文件的方法,如ReadLine()相结合next()方法工作不正常.然而,usingseek()将文件重新定位到一个绝对位置将刷新预读缓冲器. 语法 以下是next()方法的语法: ? 1

asp.net 操作iis7正在应用中使用程序方法

asp教程.net 操作iis7正在应用中使用程序方法 Microsoft.Web.Administration 命名空间里,增加了ServerManager.Site几个大类来操作IIS7. 下面是一些核心代码,可以直接使用  1)建立虚拟目录 建立虚拟目录时,默认使用"Default Web Site",也就是默认建立在Default Web Site, CreateVdir需要两个参数:虚拟路径名称和实际的物理路径    public static bool  CreateVdi

javascript操作ul中li的方法_javascript技巧

本文实例讲述了javascript操作ul中li的方法.分享给大家供大家参考.具体如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> &l

如何理解java中的某些方法不是线程安全的(不能同步访问)。

问题描述 如何理解java中的某些方法不是线程安全的(不能同步访问). 如何理解java中的某些方法不是线程安全的(不能同步访问). 能同步访问的方法有哪些,如何判断一个方法能不能同步访问 解决方案 不是线程安全的(不能同步访问) 你说反了.不是线程安全的才需要同步访问.同步访问的意思就是串行执行,等前面执行完了,再执行后面的. 线程不安全的场合很多,比如像操作系统中的用户界面.打印机等外设.控制台输出,都不允许并发(设想两个程序同时要输出文字到同一个屏幕,那还不乱套了) 在代码中,每个线程有自