原子变量与CAS算法
Posted wq3435
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原子变量与CAS算法相关的知识,希望对你有一定的参考价值。
上一节讨论了 volatile关键字,volatile关键字修饰的作用是不具有 "原子性" 和 "互斥性的"
例如 i++ 操作 就不是一个原子性的操作,i++ 其实分为3个步骤进行 "读-改-写"
int temp = i;
i = i + 1;
i= temp;
先看一段代码:
package com.java.juc; public class TestAtomicDemo { public static void main(String[] args) { AtomicDemo ad = new AtomicDemo(); for(int i = 0;i<10;i++){ new Thread(ad).start(); } } } class AtomicDemo implements Runnable{ private int seriesNumber = 0; public void run() { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getSeriesNumber()); } public int getSeriesNumber() { return seriesNumber++; } }
创建10个线程,每个线程对变量进行+1操作,
运行结果会出现如下等问题:
0
5
4
3
2
1
0
6
7
8
出现这种情况的主要原因就是 i++不是一个 原子性 操作
解决此问题的方法可以使用 原子变量
原子变量:jdk1.5以后 java.util.concurrent.atomic包下提供了常用的原子变量。
原子变量底层主要是有两个作用:
1.volatile 保证内存可见性
2.CAS(compare-And-Swap)保证数据的原子性
CAS 算法是硬件对于并发操作共享数据的支持
CAS 包含了三个操作数:
内存值 V
预估值 A
更新值 B
当且仅当 V== A 时,V = B. 否则将不做任何操作。
使用原子变量比锁的效率要高很多,使用锁时等待的线程会进入阻塞,使用Atomic进行等待的线程并不会进入阻塞状态,还是持有cpu资源,只是不断询问是否该轮到他执行了。
使用 原子变量进行改写
package com.java.juc; import java.util.concurrent.atomic.AtomicInteger; public class TestAtomicDemo { public static void main(String[] args) { AtomicDemo ad = new AtomicDemo(); for(int i = 0;i<10;i++){ new Thread(ad).start(); } } } class AtomicDemo implements Runnable{ // private int seriesNumber = 0; private AtomicInteger seriesNumber = new AtomicInteger(); public void run() { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getSeriesNumber()); } public int getSeriesNumber() { return seriesNumber.getAndIncrement(); } }
以上是关于原子变量与CAS算法的主要内容,如果未能解决你的问题,请参考以下文章