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

1 .volatile 关键字:当多个线程进行操作共享数据时, 可以保证内存中的数据可见

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

3 .模拟CAS算法

TestVolatile

package com.aff.juc;
/*
1.volatile 关键字:当多个线程进行操作共享数据时, 可以保证内存中的数据可见
                  相较于synchronized是一种较为轻量级的同步策略
注意: volatile不具备"互斥性"
     不能保证变量的原子性
*/
public class TestVolatile {
    public static void main(String[] args) {
        ThreadDemo td = new ThreadDemo();
        new Thread(td).start();
        while(true){
        //    synchronized (td) {//同步锁,刷新  效率极低
            if(td.isFlag()){
                System.out.println("------------");
                break;
                }
            //}
        }
    }
}

class ThreadDemo implements Runnable {
    private  volatile boolean flag = false;

    @Override
    public void run() {
        try {
            Thread.sleep(10);
        } catch (Exception e) {
        }
        flag = true;
        System.out.println("flag=" + isFlag());
    }

    public boolean isFlag() {
        return flag;
    }
}

TestAtomicDemo

package com.aff.juc;

import java.util.concurrent.atomic.AtomicInteger;

/*
 *
 *1.  i++  的原子性问题: i++  操作实际上分为三步 读-改-写
 *            int i = 10;
 *            i = i++;//10
 *
 *            int temp= i;
 *            i = i +1;
 *            i = temp;
 *2.  原子变量:jdk1.5后java.util.concurrent.atomic 包下提供常用的原子变量
 *                    1.具有volatile的特性(内存可见性)    private volatile int value;
 *                    2.CAS算法保证数据的 原子性
 *                              CAS算法是硬件对于并发操作共享数据的支持
 *                              CAS包含了三个操作数:
 *                                     V内存值
 *                                     A预估值
 *                                     B更新值
 *                              当且仅当 V==A, V=B   (只有当V和A相等才把B的值赋给V),否则,不做任何操作
 *
 */
public class TestAtomicDemo {
    public static void main(String[] args) {
        AtomicDemo ad = new AtomicDemo();
        new Thread(ad).start();
        for (int i = 0; i < 10; i++) {
            new Thread(ad).start();
        }
    }
}

class AtomicDemo implements Runnable {
    // private int serialNumber = 0;
    private AtomicInteger serialNumber = new AtomicInteger();// 使用原子变量

    @Override
    public void run() {
        try {
            Thread.sleep(200);
        } catch (Exception e) {
        }
        //使用原子变量就不会出现重复的了
        System.out.println(Thread.currentThread().getName() + ":" + getSerialNumber());

    }

    public int getSerialNumber() {
        // return serialNumber++;
        return serialNumber.getAndIncrement();
    }
}

TestCompareAndSwap

package com.aff.juc;

//模拟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 b = cas.compareAndSet(expectedValue, (int) (Math.random() * 100));
                    System.out.println(b);
                }
            }).start();
        }
    }
}

class CompareAndSwap {
    private int value;

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

    // 比较
    public synchronized int CompareAndSwap(int expectedValue, int newValue) {// expectedValue
                                                                             // 预估值
        int oldValue = value;
        if (oldValue == expectedValue) {// 旧的内存值和预估值进行比较
            this.value = newValue;// 替换
        }
        return oldValue;
    }

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

原文地址:https://www.cnblogs.com/afangfang/p/12630628.html

时间: 2024-10-31 18:14:58

volatile关键字与内存可见性&原子变量与CAS算法的相关文章

volatile关键字与内存可见性

前言 首先,我们使用多线程的目的在于提高程序的效率,但是如果使用不当,不仅不能提高效率,反而会使程序的性能更低,因为多线程涉及到线程之间的调度.CPU上下文的切换以及包括线程的创建.销毁和同步等等,开销比单线程大,因此需谨慎使用多线程. 在jdk1.5以后,提供了一个强大的java.util.current包,这个包中提供了大量的应用于线程的工具类. 下面开始介绍volatile关键字和内存可见性,虽然volatile是在jdk1.5之前就有的,但还是想放在这里讲一下. 举例说明 首先,我们先看

原子变量与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关键字及内存可见性

先看一段代码: package com.java.juc; public class TestVolatile { public static void main(String[] args) { ThreadDemo td = new ThreadDemo(); new Thread(td).start(); while(true){ if(td.isFlag()){ System.out.println("----------------"); break; } } } } cla

三、原子变量与CAS算法

原子变量:jdk1.5 后 java.util.concurrent.atomic 包下提供了常用的原子变量: - AtomicBoolean - AtomicInteger - AtomicLong - AtomicReference - AtomicIntegerArray - AtomicLongArray - AtomicMarkableReference - AtomicReferenceArray - AtomicStampedReference 1.以上类中的变量都是volatil

原子变量和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++就是一个非原子性操作,采用多线程再次测试:测试结果中会因为

【Java并发编程】6、volatile关键字解析&amp;内存模型&amp;并发编程中三概念

转自:http://www.cnblogs.com/dolphin0520/p/3920373.html volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以重获生机. volatile关键字虽然从字面上理解起来比较简单,但是要用好不是一件容易的事情.由于volatile关键字是与Java的内存模型有关的,因此在讲述volatile关键之前,我们先来

volotile关键字的内存可见性及重排序

在理解volotile关键字的作用之前,先粗略解释下内存可见性与指令重排序. 1. 内存可见性 Java内存模型规定,对于多个线程共享的变量,存储在主内存当中,每个线程都有自己独立的工作内存,并且线程只能访问自己的工作内存,不可以访问其它线程的工作内存.工作内存中保存了主内存中共享变量的副本,线程要操作这些共享变量,只能通过操作工作内存中的副本来实现,操作完毕之后再同步回到主内存当中,其JVM内存模型大致如下图. 而JAVA内存模型规定工作内存与主内存之间的交互协议,其中包括8种原子操作: 1)

volatile为什么可以保证内存可见性及防止指令重排序?

内存 共享主存和高速缓存(工作内存).CPU高速缓存(L1,2)产生原因读写主存没有CPU执行指令快,他是某个CPU独有,只与该CPU运行的线程有关. 内存可见性 简单的说,CPU对数据的修改,对其他CPU立刻可见.下面我们详细地说. CPU修改数据,首先对工作内存修改,再同步主内存.单线程中,变量在工作内存的副本一直有效,CPU不用每次修改从主存读取变量,只是每次修改后同步主存. 对其他CPU立刻可见.当一个CPU修改变量,同步主存,如果其他CPU的工作内存也缓存这个变量,那么这个CPU的变量

用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