三、原子变量与CAS算法

原子变量:jdk1.5 后 java.util.concurrent.atomic 包下提供了常用的原子变量:

- AtomicBoolean
- AtomicInteger
- AtomicLong
- AtomicReference
- AtomicIntegerArray
- AtomicLongArray
- AtomicMarkableReference
- AtomicReferenceArray
- AtomicStampedReference

1.以上类中的变量都是volatile类型:保证内存可见性
2.CAS算法:保证数据的原子性

CAS (Compare-And-Swap) 算法:是操作系统硬件对并发操作共享数据的支持,用于管理对共享数据的并发访问。
CAS 是一种无锁的非阻塞算法的实现。
CAS包含三个操作数

内存值 V
预估值 A
更新值 B

当且仅当,V==A 时,才将 B 的只值赋给 A,否则,将不做任何操作。  //(CAS算法的一个特性)

代码示例:

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 volatile int serialNumber = 0;

    private AtomicInteger serialNumber = new AtomicInteger(0);

    @Override
    public void run() {

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
        }

        System.out.println(getSerialNumber());
    }

    public int getSerialNumber(){
        return serialNumber.getAndIncrement();//实现i++操作
    }
}

[注] i++ 的实现原理

i++ 的原子性问题:i++ 的实际上分为三个步骤:"读 - 改 - 写"
即,i++的底层实际上是:
    int temp=i; //temp 是个临时变量
    i=i+1;
    i=temp;

模拟CAS算法 :

CAS的流程:获取 —> 比较 —> 设置

public class TestCompareAndSwap {
    public static void main(String[] args) {
        final CompareAndSwap cas=new CompareAndSwap();

        for(int i=0;i<10;i++){
            new Thread(new Runnable(){
                @Override
                public void run() {
                    int expectedValue=cas.get(); //每次执行前先获取内存中的值
                    boolean isTrue=cas.compareAndSet(expectedValue, (int)(Math.random()*101));
                    System.out.println(isTrue);
                }
            }).start();
        }
    }
}

class CompareAndSwap{
    //内存值
    private int value;

    //获取内存值
    public synchronized int get(){
        return value;
    }

    //比较
    public synchronized boolean compareAndSwap(int expectedValue,int newValue){
        int oldValue=value;//线程读取内存值,与预估值比较
        if(oldValue==expectedValue){
            this.value=newValue;
            return true;
        }
        return false;
    }

    //设置
    public synchronized boolean compareAndSet(int expectedValue,int newValue){
        return expectedValue == compareAndSwap(expectedValue,newValue);
    }
}

原文地址:https://www.cnblogs.com/zongheng14/p/10703822.html

时间: 2024-11-07 07:22:49

三、原子变量与CAS算法的相关文章

原子变量与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[

volatile关键字与内存可见性&amp;原子变量与CAS算法

1 .volatile 关键字:当多个线程进行操作共享数据时, 可以保证内存中的数据可见 2 .原子变量:jdk1.5后java.util.concurrent.atomic 包下提供常用的原子变量 3 .模拟CAS算法 TestVolatile package com.aff.juc; /* 1.volatile 关键字:当多个线程进行操作共享数据时, 可以保证内存中的数据可见 相较于synchronized是一种较为轻量级的同步策略 注意: volatile不具备"互斥性" 不能保

原子变量和CAS算法以及ConcurrentHashMap

1.首先做一个测试:i++.输出结果为10,因为在底层实现的时候会引入一个临时变量具体为: 1 public static void main(String[] args) { 2 //i++测试: 3 int i=10; 4 i=i++; 5 System.out.println(i); 6 /* 7 *底层原理: 8 _temp = i ; 9 i = i + 1 ; 10 i = _temp ; 11 * */ 12 } 所以i++就是一个非原子性操作,采用多线程再次测试:测试结果中会因为

并发编程(三)__模拟CAS算法

1 /* 2 * 模拟 CAS 算法 3 */ 4 public class TestCompareAndSwap { 5 6 public static void main(String[] args) { 7 final CompareAndSwap cas = new CompareAndSwap(); 8 9 for (int i = 0; i < 10; i++) { 10 new Thread(new Runnable() { 11 12 @Override 13 public vo

用Java原子变量的CAS方法实现一个自旋锁

为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. http://www.cnblogs.com/shijiaqi1066/p/5999610.html 实现: package sjq.mylock; import java.util.concurrent.atomic.AtomicReference; public class SpinLock { private AtomicReference<Thread> owner = new

个人笔记--内存可见性和原子变量

jdk1.6以后提供了java并发包. volatile与内存可见性: 例子: 结果: 结论: main()线程读取到的td.isFlag并不是true. 这就涉及到了内存可见性问题. 具体原因: 重排序:代码书写的顺序与实际执行的顺序不同. 1.  编译器重排序 2.  指令重排序 3.  内存系统重排序 As-if-serial: 无论如何重排序,程序执行的记过应该与代码顺序执行的结果一致.Java编译器和处理器在运行时都会保证在单线程下遵循这个语言. 补充:jstack可以生成线程快照(j

2.原子变量 CAS算法

前面提到,使用volatile无法保证 变量状态的原子性操作,所谓原子性,就是不可再分 如:i++的原子性问题,i++ 的操作实际上分为三个步骤  "读-改-写" (1)保存i的值(一个临时变量中) (2)递增i (3)返回已保存的值 当在并发的条件下执行 i++, 线程1执行 i++,先从主存中 获取 i 的 值(假设初值i=0),还未等 执行i = i + 1,此时线程2进来,也从主存中获取 i 的 值(0) 然后 线程1 执行了 i = i + 1:(i=1) 线程2再执行 i

Java并发——原子变量和原子操作与阻塞算法

十五年前,多处理器系统是高度专用系统,要花费数十万美元(大多数具有两个到四个处理器).现在,多处理器系统很便宜,而且数量很多,几乎每个主要微处理器都内置了多处理支持,其中许多系统支持数十个或数百个处理器. 要使用多处理器系统的功能,通常需要使用多线程构造应用程序.但是正如任何编写并发应用程序的人可以告诉你的那样,要获得好的硬件利用率,只是简单地在多个线程中分割工作是不够的,还必须确保线程确实大部分时间都在工作,而不是在等待更多的工作,或等待锁定共享数据结构. 问题:线程之间的协调 如果线程之间 

并发策略-CAS算法

对于并发控制而言,我们平时用的锁(synchronized,Lock)是一种悲观的策略.它总是假设每一次临界区操作会产生冲突,因此,必须对每次操作都小心翼翼.如果多个线程同时访问临界区资源,就宁可牺牲性能让线程进行等待,所以锁会阻塞线程执行. 与之相对的有一种乐观的策略,它会假设对资源的访问是没有冲突的.既然没有冲突也就无需等待了,所有的线程都在不停顿的状态下持续执行.那如果遇到问题了无锁的策略使用一种叫做比较交换(CAS Compare And Swap)来鉴别线程冲突,一旦检测到冲突产生,就