Java并发之原子变量及CAS算法-上篇
概述
本文主要讲在Java并发编程的时候,如果保证变量的原子性,在JDK提供的类中式怎么保证变量原子性的呢?。对应Java中的包是:java.util.concurrent.atomic包下。因为涉及到了CAS算法,需要对CAS算法讲解及CAS算法三个问题怎么解决以及和Synchroized比较。文章比较长,所以就分为上下两个篇幅讲解。本文是上篇《Java并发之原子变量及CAS算法-上篇》
本文是《凯哥分享Java并发编程之J.U.C包讲解》系列教程中的一篇。如果想系统学习,建议从第一篇开始看。
原子变量案例
在Java中有一种写法:int i = 10; i++ 这种写法。
我们先来看看:
输入的是0还是1呢 ?
I++输出0的原因分析
答案是:0。为什么呢?凯哥把编译后的class文件反编译,咱们看:
说明:i的操作是i++;y的操作是++y.
从反编译后的代码,我们可以看到i++在JVM中的操作,总共分三步:
第一步:声明变量var10000 ,然后将i赋值给var10000,此时var10000的值是0;
第二步:声明变量var3 然后把i+1 赋值给var3,此时,var3的值等于1了;
第三步:将变量var10000的值又赋值给了i,此时因为var10000的值是0,所以i的值也是0
所以在sysout(i)的时候,就输出了0.
我们分析上面1,2,3步骤,可以发现。其实i++执行的是:读取-修改-重写 三个操作。
既然读写操作,就会涉及到变量原子性。测试在多线程下变量原子性
测试多线程下的变量原子性
那么,如果我们把对i的操作放到多个线程中操作结果会是什么样的呢?
线程操作I的代码:
开启十个线程同时操作i的代码:
我们来看看运行结果:
从运行结果中,我们可以看到,线程Thread-5和线程Thread-8的值是一样的。
根据上面运行的场景,我们发现,变量i其实是十个线程中的共享变量。从运行的结果来看,多个线程操作后,结果出问题了。
不同线程在内存中运行模拟图:
线程1;线程2;以及主线程之间运行关系,可以详见凯哥上一篇文章:《Java并发之内存可见性问题怎么解决》。这篇文章详细讲解了怎么关系。
已经看过凯哥上一篇文章或者是知道volatile关键字的朋友可能要说,这不就是线程之间变量可见性问题嘛。使用volatile关键字修饰i就可以了。真的可以了吗?
我们修改程序,用volatile来修饰,看看运行结果:
使用volatile关键字是否能解决多线程情况下变量原子性呢?
用volatile来修饰变量:
private volatile int shardData = 0;
运行结果:
我们发现,就算使用volatile关键字修饰了,依然存在多线程下变量原子性的问题。
怎么解决这种并发下变量原子性问题呢?
Java的atomic包
在jdk1.5以后,Java为我们提供了一个常用的原子变量。都在:java.util.concureent.atomic包下。我们来看看,都有哪些:
从JDK的API文档中(凯哥使用的是JDK1.8的API)我们可以看到常用的原子性变量。
怎么保证原子性呢?
那么,在atomic包下的这些类怎么保证原子性呢?
1:该包下的变量都是使用volatile关键字来修饰。
解决了多线程之间变量可见性。
Int类型的原子性对象AtomicInteger对象中:
用于对象的AtomicReference对象中:
都是使用volat关键字修饰的。
2:使用CAS算法
保持了变量的原子性
总结:
在Java的JDK中提供了concurrent.atomic包,使用这个包下的对象创建的变量就能保证原子性。
保证原子性的策略:
1:变量都是用Volatile关键字修饰。来保证内存可见性
2:使用CAS算法,来保证原子性。
凯哥个人博客:www.kaigejava.com
凯哥公众号:凯哥Java(kaigejava)
下篇预告:
在下一篇文章中,我们主要讲解CAS算法原理及CAS算法会参数哪些问题(三个问题)?JDK是怎么解决的?修改i++使其成为具有原子性变量怎么实现。
相关推荐
在Java并发编程中,CAS(Compare and Swap)是一种无锁算法,用于在多线程环境中实现对共享变量的原子性更新。相比于传统的锁机制,如`synchronized`和`Lock`,CAS具有更低的开销,因为它避免了线程阻塞。本文将深入...
Java并发编程是多线程环境下确保程序正确执行的关键技术,其中原子变量和非阻塞同步机制扮演着重要角色。非阻塞算法不同于传统的基于锁的同步机制,它们允许线程在不阻塞其他线程的情况下进行操作,提高了系统的并发...
- **原子变量**:原子变量提供了一种简单的方式来更新基本类型的值,而无需显式同步。书中详细介绍了`AtomicInteger`等类的使用。 ##### 3. 并发工具与框架 - **Executor框架**:Executor框架提供了一种管理线程池...
- **java.util.concurrent.atomic**包:原子变量类如`AtomicInteger`、`AtomicReference`等,它们提供无锁编程的支持。 - **Compare and Swap (CAS)**:理解CAS算法的工作原理,以及它如何避免锁竞争提高并发性能...
- **原子变量的工作原理:** 分析原子变量的内部实现机制,例如CAS算法的应用。 - **使用原子变量优化性能:** 讨论在哪些场景下使用原子变量可以有效提升程序性能。 **5. 并发集合类详解** - **`...
- **java.util.concurrent.atomic** 包:原子变量类如AtomicInteger、AtomicLong等,以及如何使用CompareAndSwap(CAS)无锁算法实现线程安全的操作。 5. **线程池** - **ExecutorService**:理解ExecutorService...
Java并发编程实践中,第八章主要探讨了原子变量和非阻塞算法在处理并发问题时的重要性和优势,以克服传统锁机制的局限性。锁在多线程环境下提供了对共享资源的互斥访问,但同时也存在一些明显的劣势。 首先,锁的...
Java并发编程是Java语言中最为复杂且重要的部分之一,它涉及了多线程编程、内存模型、同步机制等多个领域。为了深入理解Java并发编程,有必要了解其核心技术点和相关实现原理,以下将详细介绍文件中提及的关键知识点...
在探讨Java并发编程与高并发解决方案之前,我们首先需要理解几个关键概念:并发(Concurrency)、高并发(High Concurrency)以及多线程(Multithreading)。这些概念是现代软件开发中不可或缺的一部分,尤其是在...
6. **原子操作与CAS**:Java的`java.util.concurrent.atomic`包提供了原子变量类,如AtomicInteger、AtomicReference等。它们使用无锁的CAS(Compare and Swap)算法实现线程安全的更新,具有高效率和低开销的特点。...
本文主要讲述了 Java 中的并发编程,包括 atomic 包的介绍、CAS 算法的原理、ABA 问题的解决方案,以及 collections 中的 HashMap、HashTable 和 ConcurrentHashMap 的源码分析。 Atomic 包的介绍 ----------------...
5. **原子变量类**:AtomicInteger、AtomicLong等,它们提供了无锁编程的能力,通过CAS(Compare and Swap,比较并交换)操作实现原子性更新,提高了并发性能。 6. **线程池**:Executor框架是Java并发编程的重要...
4. **原子操作与CAS**:Atomic类库中的原子变量支持无锁编程,使用Compare-and-Swap(CAS)操作实现线程间的协作,避免死锁和活锁问题。 5. **并发工具类**:ExecutorService、Future和Callable接口是Java并发编程...
`java.util.concurrent.atomic`包提供了原子变量类,如AtomicInteger和AtomicReference,它们通过CAS(Compare and Swap)无锁算法实现线程安全的更新操作。 10. **中断和异常处理** Thread类的interrupt()方法...
在Java中,常见的乐观锁实现是无锁编程,如使用原子类(AtomicInteger、AtomicLong等)中的CAS(Compare and Swap)算法。悲观锁则假设在读取数据时会有其他线程修改,所以在读取时即加锁,如`synchronized`关键字和...
Java是企业级应用开发的重要选择,尤其是在大型分布式系统中,其强大的并发处理能力是关键特性之一。下面将详细阐述相关知识点。 1. **并发基础** - **线程与进程**:理解线程与进程的区别,线程是程序执行的最小...