public class VolatileTest {
public static void main(String[] args) {
ThreadDemo td = new ThreadDemo();
new Thread(td).start();
while(true){
if(td.getFlag()){
System.out.println("========");
break;
}
} }
}
class ThreadDemo implements Runnable{
private boolean flag=false; @Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag=true;
System.out.println("flag="+getFlag()); }
public boolean getFlag(){
return flag;
}
}

flag是main thread和td共享的数据,他们都在各自的线程内有一个copy,由于while true的速度十分快,main thread不能读取到td修改后的值,所以只能输出 flag=true。

内存不可见性:当多个thread操作共享数据时,彼此不可见

volatile:当多个thread操作共享数据时,保证数据是可见的,内存栅栏   可以理解为多个线程直接操作主存中的数据

因为使用vloatile 不能指令重排  所以效率低

volatile相比synchronized:

  是一种较为轻量级的同步策略,volatile不具备互斥性,两个线程可以同时访问共享数据,volatile不能保证变量的原子性,

原子性问题:i++

  

以下情况使用volatile不能解决非原子性问题:内存可见性问题依然存在

public class AtomicTest {
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 serialNum=0;
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+getSerialNum());
}
public int getSerialNum(){
return serialNum++;
}
}

二、使用源自变量 java.util.concurrent.atomic 原子变量包

  1.使用volatile保证内存可见性

  2.使用CAS compare and swap算法保证数据的原子性

    CAS是硬件对于并发操作共享数据的支持  

    CAS包含三个操作数:

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

(1)首先读取内存之V 在替换的时候读取旧值A

AtomicInteger:保证线程安全  内存可见性 原子性问题

private AtomicInteger serialNum=new AtomicInteger();
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+getSerialNum());
}
public int getSerialNum(){
return serialNum.getAndIncrement();
}

CAS算法的模拟:

public class TestCAS {
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 expectVal = cas.get();
boolean b= cas.compareAndSwap(expectVal,(int)(Math.random()*101));
}
}).start();
}
}
} class CompareAndSwap {
private int value;
public synchronized int get() {
return value;
}
public synchronized int cas(int expectVal, int newVal) {
int oldVal = value;
if (oldVal == expectVal)
this.value = newVal;
return oldVal;
}
public synchronized boolean compareAndSwap(int expectVal, int newVal) {
return expectVal==cas(expectVal,newVal);
}
}

JUC--volatiley&CAS的更多相关文章

  1. 一段JAVA代码了解多线程,JUC、CAS原子性操作。

    @Test public void testPaceController_multiThread() throws InterruptedException { final PaceControlle ...

  2. JUC之CAS

    CAS(全称为CompareAndSwap,也有说是CompareAndSet,都差不多)是一条CPU并发原语,它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,判断预期值和更改新值的 ...

  3. JUC

    1.Java JUC简介 在Java5.0提供了java.util.concurrent(简称JUC)包,在此包中增加了在并发编程中很常用的实用工具类,用于定义类似于线程的自定义子系统,包括线程池.异 ...

  4. juc-2.1-模拟CAS算法

    package com.wf.zhang.juc; /* * 模拟 CAS 算法 */ public class TestCompareAndSwap { public static void mai ...

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

    1 .volatile 关键字:当多个线程进行操作共享数据时, 可以保证内存中的数据可见 2 .原子变量:jdk1.5后java.util.concurrent.atomic 包下提供常用的原子变量 ...

  6. Spring Cloud--尚硅谷2020最新版

    Spring Cloud 初识Spring Cloud与微服务 在传统的软件架构中,我们通常采用的是单体应用来构建一个系统,一个单体应用糅合了各种业务模块.起初在业务规模不是很大的情况下,对于单体应用 ...

  7. java多线程系列 JUC原子类 CAS及原子类

    根据数据类型,可以将JUC包中的原子操作类可以分为4类. 1. 基本类型: AtomicInteger, AtomicLong, AtomicBoolean ;2. 数组类型: AtomicInteg ...

  8. 【Java_多线程并发编程】JUC原子类——原子类中的volatile变量和CAS函数

    JUC中的原子类是依靠volatile变量和Unsafe类中的CAS函数实现的. 1. volatile变量的特性 内存可见性(当一个线程修改volatile变量的值后,另一个线程就可以实时看到此变量 ...

  9. java并发编程(十三)----(JUC原子类)引用类型介绍(CAS和ABA的介绍)

    这一节我们将探讨引用类型原子类:AtomicReference, AtomicStampedRerence, AtomicMarkableReference.AtomicReference的使用非常简 ...

  10. JUC原子操作类与乐观锁CAS

    JUC原子操作类与乐观锁CAS ​ 硬件中存在并发操作的原语,从而在硬件层面提升效率.在intel的CPU中,使用cmpxchg指令.在Java发展初期,java语言是不能够利用硬件提供的这些便利来提 ...

随机推荐

  1. iOS CATransition 自定义转场动画

    https://www.jianshu.com/p/39c051cfe7dd CATransition CATransition 是CAAnimation的子类(如下图所示),用于控制器和控制器之间的 ...

  2. keras01 - hello world ~ 搭建第一个神经网络

    import numpy as np from keras.datasets import mnist from keras.models import Sequential, Model from ...

  3. Spring 完成自动注入(autowire)

    目录 两个测试类 普通方式手动注入 普通方式注入的缺点 自动注入的介绍 配置自动注入的方式 配置全局自动注入 局部单独配置 利用注解实现自动注入 两个测试类 package cn.ganlixin.p ...

  4. 四、Jedis操作Redis

    前言:  原来我们操作mysql需要用的jdbc,现在操作redis则需要jedis,jedis是客户端,而redis是服务器,使用jedis客户端来操作redis. 在这里要使用jedis操作red ...

  5. springmvc的前端控制器

    <servlet> <servlet-name>xxx</servlet-name> <servlet-class>org.springframewor ...

  6. 【pytorch】pytorch-backward()的理解

    pytorch-backword函数的理解 函数:\(tensor.backward(params)\) 这个params的维度一定要和tensor的一致,因为tensor如果是一个向量y = [y1 ...

  7. 接入HTTPS协议的CAS登录配置

    1.在CAS服务器创建tomcat.keystore(记住keystone创建时输入的密码) keytool -genkeypair -alias "tomcat" -keyalg ...

  8. C++ 中 double、 long double、long 和 long long

    double 属于浮点类型,具体为双精度浮点类型,通常为 IEEE-754 64 位浮点类型. long double 也属于浮点类型,具体为扩展精度浮点类型,其精度不低于double,具体由编译器和 ...

  9. DRF 商城项目 - 用户( 登录, 注册,登出,个人中心 ) 逻辑梳理

    用户登录 自定义用户登录字段处理 用户的登录时通过 手机号也可以进行登录 需要重写登录验证逻辑 from django.contrib.auth.backends import ModelBacken ...

  10. WD与地图 解题报告

    WD与地图 哎,我好傻啊,看了题解还弄错了一遍,靠着lbw指点才董 题意:给一个带点权有向图,要求支持删边,查询一个scc前\(k\)大权值,修改点权,不强制在线. 显然倒序处理变成加边 考虑求出每条 ...