`

Java并发编程之CAS二源码追根溯源

阅读更多

Java并发编程之CAS二源码追根溯源

在上一篇文章中,我们知道了什么是CAS以及CAS的执行流程,在本篇文章中,我们将跟着源码一步一步的查看CAS最底层实现原理。

本篇是《凯哥(凯哥Java:kagejava)并发编程学习》系列之《CAS系列》教程的第二篇:从源码追根溯源查看CAS最底层是怎么实现的。

本文主要内容:CAS追根溯源,彻底找到CAS的根在哪里。

一:查看AtomicInteger.compareAndSet源码

通过上一篇文章学习,我们知道了AtomicInteger.compareAndSet方法不加锁可以保证原子性(其原理就是unsafe+cas实现的),我们来看看其源码:

思考1:变量可见性

AtomicInteger对象(下文凯哥简称:atoInteger)怎么保证变量内存可见性呢?

查看源码:

 

思考2:为什么上一篇13行的i.compareAndSet(1,1024)是false

我们来看看atoInteger的compareAndSet方法。凯哥在上面添加了注释。

 

在调用unsafe的compareAndSwapInt这个方法的时候,unsafe是什么?this指的是什么?valueOffset又是什么呢?

我们接着查看atoInteger源码:

 

我们发现Unsafe以及valueOffset都是从一个对象中获取到的。

那么this指的是什么?其实this就是当前atoInteger对象。

那么Unsafe对象在哪里呢?

 

 

 

我们想要看源码,怎么查看呢?发现不能看源码啊。别急,这个文件的源码可以从openJdk的源码中查到。

接着,我们来查看OpenJdk8的源码:

(PS:下载OpenJdk8源码凯哥这里就不赘述了。在文章最后,凯哥给出)

下载完,解压之后,文件位置:openjdk\jdk\src\share\classes\sun\misc。如下图:

 

我们来看看Unsafe类上面的注解:

 

A collection of methods for performing low-level, unsafe operations.

什么意思呢?用于执行底层的(low-level,)、不安全操作的方法的集合。

就是说,这个类可以直接操作底层数据的。

需要说明的是:在这个对象中大量的方法使用了native来修饰(据网友统计高达82个)

 

我们知道,Java的方法使用native关键字修饰的,说明这个方法不是Java自身的方法(非Java方法),可能调用的是其他语言的。如C或C++语言的方法。

我们再来看看:unsafe.objectFieldOffse()中的

 

这个方法就是返回一个内存中访问偏移量。

return unsafe.compareAndSwapInt(this, valueOffset, expect, update);

 

在unsafe类中compareAndSwapInt方法也是native的。我们在来看看这个方法调用操作系统底层C++的代码:

 

说明:

jint *addr:主内存中的变量值

old:对象工作区域的值

new_val:将要改变的值。

这三个是不是很熟悉,对。就是CAS的三个参数。

 

分析第13行为什么返回false:

在11行的时候,设置主内存的变量值V=1.

在12行后,更新为V=2020了。

当执行到第13行的时候,

主内存:V=2020

程序工作区变量值jint *addr A的值:A=1

new_val:1024。

从调用C++代码我们可以分析到:

 

在第5行的时候,因为1!=2020,所以return 的result就是false.

所以第13行输出的是false.

思考3:atoInteger.getAndIncrement()是怎么保证数据一致性的

 

调用的是getAndAddInt方法。接着查看unsafe的源码,就会发现CAS保证原子性的终极代码。

CAS保证原子性终极方法,如下图:

 

看看:getObjectVolatile。方法发现是native.如下图:

 

再来看看compareAndSwapObject:

 

发现是native修饰的方法。说明不是Java的方法。这个我们等会再细说。

先来研究getAndSetObject:

 

源码:

 

我们来模拟:atoInteger.getAndIncrement();

假设默认值是0. 主内存的值是0

在调用getAndSetObject方法的几个参数说明:

Var1:当前atoInteger对象

Var2:当前偏移量(内存地址所在位置。如:三排四列)

Vart4:默认就是1

Var5:获取到的主内存的值

Var5+var4:将要更新的值。

从源码,我们看到是do while语句。为什么不是while语句呢?因为先要获取到主内存中变量最新的值,然后再判断。所以选用了do while语句。

我们来看看当CPU1线程1和CPU2线程B来执行的时候:

 

两个线程都从主内存copay了i的值到自己工作内存空间后,进行+1的操作。

假设线程1再执行+1操作后,准备往主内存回写数据的时候,CPU1被挂起。然后CPU2竞争到资源之后,也操作i+1后,将更新后的值回写到了主内存中。然后切换到CPU1了,CPU1接着执行。对比代码分析:

 

线程1在执行do后得到的值var5=1而不是0

然后while里面执行:var1和var2运算后的结果是0(工作区的值)。

因为0!=5 .所以this.comparAndSwapInt的值是false.

又因为前面有个! 非得符号。也就是!false。我们知道!false就是true.

也就是while(true)。While(true)后,接着循环执行。线程会放弃原有操作,重新从主内存中获取到最新数据(此时就是1了),然后再进行操作后。

又到了do,获取在主内存最新数据是1.接着走while()

因为,var1,var2获取到工作区的值是1 var5也等于1.1=1,成立了,执行var5+var5=1+1=2,来更新主内存的数据后返回true.

又因为前面有个!非的符号。所以就是while(!true),也就是while(false)。退出循环,返回var5的值。

结论:

通过上面的运行分析,我们发现atoInteger的getAndIncrement方法保证原子性是unsafe+CAS来保证变量原子性的(其中do while语句就是后面我们将要学到的自旋)

0
3
分享到:
评论

相关推荐

    java并发编程实战源码,java并发编程实战pdf,Java

    《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...

    Java并发编程实践高清pdf及源码

    《Java并发编程实践》是一本深入探讨Java多线程编程的经典著作,由Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowles和David Holmes等专家共同编写。这本书全面介绍了Java平台上的并发编程技术,是Java开发...

    java并发编程实战中文加英文版加源码

    JAVA并发编程实践中文版 英文版 原书源码 带书签 java_concurrency_in_practice.pdf 英文版还是不错的,但是中文版的译者典型的没有技术功底,介绍上说什么专家, 翻译的非常差劲,有些句子都不通顺,都不知道自己去...

    java 并发编程的艺术pdf清晰完整版 源码

    《Java并发编程的艺术》这本书是Java开发者深入理解并发编程的重要参考书籍。这本书全面地介绍了Java平台上的并发和多线程编程技术,旨在帮助开发者解决在实际工作中遇到的并发问题,提高程序的性能和可伸缩性。 ...

    Java并发编程从入门到精通源码.rar

    再者,`java.util.concurrent.atomic`包中的原子类提供了非阻塞的线程安全操作,如`AtomicInteger`、`AtomicLong`等,它们使用CAS(Compare and Swap)操作实现无锁编程,提高了并发性能。 最后,死锁、活锁和饥饿...

    JAVA并发编程艺术 高清pdf

    JAVA并发编程艺术 高清pdf : 1.并发变成的挑战 2. java并发机制的底层实现原理 3. java 内存模型 4. java并发编程基础 5.java中的锁。。。。。。。

    java并发编程实践高清中文版+源码

    《JAVA并发编程实践》随着多核处理器的普及,使用并发成为构建高性能应用程序的关键。Java 5以及6在开发并发程序中取得了显著的进步,提高了Java虚拟机的性能以及并发类的可伸缩性,并加入了丰富的新并发构建块。在...

    JAVA并发编程实践.pdf+高清版+目录 书籍源码

    《JAVA并发编程实践》这本书是Java开发者深入理解并发编程的重要参考资料。它涵盖了Java并发的核心概念、工具和最佳实践,旨在帮助读者在多线程环境下编写高效、安全的代码。 并发编程是现代软件开发中的关键技能,...

    Java 并发编程实战.pdf

    《Java并发编程实战》这本书是关于Java语言中并发编程技术的经典著作。它详细介绍了如何在Java环境中有效地实现多线程程序和并发控制机制。在Java平台上,由于其本身提供了强大的并发编程支持,因此,掌握并发编程...

    java并发编程艺术

    《Java并发编程艺术》这本书深入探讨了Java平台上的并发编程技术。并发编程是现代多核处理器环境下提升软件性能的关键手段,而Java语言提供了丰富的工具和API来支持这一领域。本书旨在帮助开发者理解和掌握如何在...

    深入分析Java并发编程之CAS

    在Java并发编程中,CAS(Compare and Swap)是一种无锁算法,用于在多线程环境中实现对共享变量的原子性更新。相比于传统的锁机制,如`synchronized`和`Lock`,CAS具有更低的开销,因为它避免了线程阻塞。本文将深入...

    Java并发编程从入门到精通(pdf)(附源码)

    总的来说,《Java并发编程从入门到精通》不仅覆盖了Java并发编程的全面知识,还提供了丰富的实践案例和源码,是Java开发者提升并发编程能力的理想教材。通过深入学习这本书,你将能够掌握并发编程的核心技巧,为成为...

    《java 并发编程实战高清PDF版》

    在Java并发编程中,多线程是核心概念之一。多线程允许程序同时执行多个任务,从而充分利用系统资源,提高程序性能。然而,多线程编程也带来了同步和竞态条件等问题,这需要开发者具备良好的线程管理和同步机制的知识...

    java并发编程2

    Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。以下是对标题和描述中所提及的几个知识点的详细解释: 1. **线程与并发** - **线程*...

    java并发编程源码

    《Java并发编程源码》是深入理解Java多线程编程技术的重要参考资料,它包含了实际案例和源代码,有助于开发者在实践中提升并发编程能力。这里主要围绕"并发"和"源码"这两个关键标签,详细讲解Java并发编程的核心知识...

    JAVA并发编程艺术pdf版

    《JAVA并发编程艺术》是Java开发者深入理解和掌握并发编程的一本重要著作,它涵盖了Java并发领域的核心概念和技术。这本书详细阐述了如何在多线程环境下有效地编写高效、可靠的代码,对于提升Java程序员的技能水平...

    Java并发编程实战华章专业开发者书库 (Tim Peierls 等 美Brian Goetz).pdf

    《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南,由Tim Peierls等人与Brian Goetz合著,旨在帮助Java开发者理解和掌握在多线程环境中编写高效、安全的代码。这本书由拥有丰富经验的JDK并发大师及...

    java并发编程实战源码 附有本书所有源码,maven 导入 eclipse或idea

    除了提供读者全面指南编写并发Java应用程序的书籍“Java Concurrency in Practice”外,还可以下载相关源代码。这包括书中使用的所有源代码示例,可以使用Maven轻松地将其导入Eclipse或IntelliJ IDEA中。通过实践源...

Global site tag (gtag.js) - Google Analytics