很早之前在公司就看到了atomicInteger,atomicLong这些变量了,一直不明白是什么意思,今天花了点时间了解下。

volatile:

先从volatile开始讲起,volatile是多线程中会使用的关键字,volatile不加锁(即不会线程阻塞,但不安全),但保证了可见性(一个线程修改,立即刷新到主内存,对其他线程可见)和禁止指令重排序。但是这样依然对存在一个问题,就是多线程时候来不及刷新到主内存中,新线程就获取到了旧数据。例如下面代码:

错误原因:有的线程已经把a进行了加1操作,但是还没来得及重新刷入到主存,其他的线程就重新读取了旧值。因为才造成了错误

package atomic;

import java.util.concurrent.atomic.AtomicInteger;

/**
* @ProjectName: AtomicIntegerTest
* @Package: atomic
* @Description:
* @Author: huyuqiao
* @CreateDate: 2020/9/21 14:25
*/
//Volatile:无法保证最后a结果一定是50
//AtomicInteger:虽然最后顺序不一样,但是最终a一定是50
public class AtomicIntegerTest {
// private static volatile int a = 0;
static AtomicInteger a = new AtomicInteger();
public static void main(String[] args){
AtomicIntegerTest atomicIntegerTest = new AtomicIntegerTest();
Thread[] threads = new Thread[5];
for (int i = 0; i < 5; i++) {
threads[i] = new Thread(() ->{
try{
for (int i1 = 0; i1 < 10; i1++) {
// System.out.println(a++);
System.out.println(a.incrementAndGet());
Thread.sleep(500);
}
} catch (Exception e){
e.printStackTrace();
}
});
threads[i].start();
}
}
}
atomicInteger

上面代码中atomicInteger却保证了数据的完整性,原因就在于内部CAS原理(compare and swap)

CAS 即比较并替换,实现并发算法时常用到的一种技术。CAS操作包含三个操作数——内存位置、预期原值及新值。执行CAS操作的时候,将内存位置的值与预期原值比较,如果相匹配,那么处理器会自动将该位置值更新为新值,否则,处理器不做任何操作。

但是这样会有一个ABA问题,就是虽然你保证了数据最终一定一直,但是无法保证数据中途会被修改,即ABA问题(变量A->B->A中途会被修改)

ABA问题解决办法:解决使用AtomicStampReference.getstamp标记更新次数,若没被更新,则正确,否则报错。

面试问题:并发编程(原子性、可见性、一致性)

Java-学习日记(Atomic,Volatile)的更多相关文章

  1. [转]Java学习日记之 volatile

    用在多线程,同步变量. 线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B.只在某些动作时才进行A和B的同步.因此存在A和B不一致的情况.volatile就是用来 ...

  2. Java学习日记-2 零零碎碎

    一.使用Scanner类进行控制台的输入 文档中Scanner类的定义为A simple text scanner which can parse primitive types and string ...

  3. Java学习日记基础篇(六)—— 抽象类、接口、final

    抽象类 为什么要有抽象类? 因为父类方法有不确定性,我们在Animal中定义了一个方法,但是它会被子类的方法覆盖掉,我们就不知道这个方法原本是做什么的 public class test1 { pub ...

  4. Java学习日记基础(五)——类、对象之this、静态变量(类变量)、静态方法(类方法)、四大特征

    this 赵本山问奥尼尔:“我的爸爸的爸爸是谁?” 奥尼尔:“不知道” 赵本山:“你傻啊,是我爷爷” 奥尼尔回去问科比:“我的爸爸的爸爸是谁?” 科比:“不知道” 奥尼尔:”你傻啊,是赵本山的爷爷“ ...

  5. Java学习日记基础篇(四)——类,对象之成员变量,成员方法,构造方法

    面向对象(Object Oriented) 一.面向对象杂谈 面向对象(Object Oriented),我的翻译是以物体为目标的,就是说编程的时候是建立一个物体,然后对这个物体进行操作. Java语 ...

  6. Java学习日记——基础篇(二)基本语法

    变量 变量和常量是程序处理的两种基本数据对象,变量是程序的基本组成单位 变量的目的就是确定目标并提供存放空间 public class Hello { public static void main( ...

  7. Java学习日记之 Java-其他类型

    OK , 就绪, 第一篇博客开撸 ~ 先听了毕姥爷激情澎湃的其他类型 ,从这里开始入手吧 : (一)System类  System类代表系统类,系统的属性和方法都放在该类.System类是一个fina ...

  8. Java学习日记之 Java-IO流

    Java中的IO流在处理上分为字节流和字符流.字节流和字符流的区别 : 1.字节流读取的时候,读到一个字节就返回一个字节:  字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8 ...

  9. Java学习日记-10 集合

    集合(Collection) 1. 什么是集合? 集合是一组对象组成的一个整体,又称为容器,集合类属于java.util包.集合不同于数组的地方在于,一是它的容量是可变的,二是集合中只能存储对象,不能 ...

随机推荐

  1. 【敏杰开发】Beta阶段项目展示

    [敏杰开发]Beta阶段项目展示 项目相关地址汇总 线上地址:http://roadmap.imcoming.top 前端仓库:https://github.com/MinJieDev/Roadmap ...

  2. 【BUAA软工】Beta阶段测试报告

    项目 内容 班级:北航2020春软件工程 博客园班级博客 作业:Beta阶段测试报告 测试报告 发现的bug Beta阶段的bug [已解决]CPP项目无法进行调试 [已解决] 注册界面注册后不能够自 ...

  3. 吃透KVM创建虚机和KVM命令

    1.创建虚拟机 1.1创建虚拟机磁盘 #使用qemu命令来创建磁盘 qemu-img create -f qcow2 /var/lib/libvirt/images/centos7.2.qcow2 2 ...

  4. Jekyll+GitHub Pages部署自己的静态Blog

    混了这么久,一直想拥有自己的博客,通过jekyll和GitHub Pages捣腾出了自己的博客(https://www.ichochy.com) 一.安装jekyll 首先有安装Ruby的开发环境 运 ...

  5. SSH连接自动断开的解决方法(deb/rpm)

    ######### 修改后的: ## # tail -f -n 20 sshd_config#MaxStartups 10:30:60#Banner /etc/issue.net # Allow cl ...

  6. hard way for code

    奋斗吧骚年:https://learncodethehardway.org/ 有关linuxz命令的URL:man.linuxde.net

  7. Linux中级之负载均衡(lvs,nginx,haproxy)、中间件

    一.负载均衡的概念 1.系统的扩展方式: scale up:向上扩展 scale out:向外扩展 2.集群类型:  LB(Load Balancing).HA(high availability) ...

  8. spark_shuffle方式的演进过程

    spark shuffle有四种方式,分别是 hashshuffle 优化后的hashshuffle sortshuffle bypass 一.hashshuffle与优化 一开始spark的shuf ...

  9. MarkDown笔记一

    目录 目录 字体 标题 下划线标题 #号标题 加重与斜体 高亮 删除线 上标与下标 脚注 转义字符 分割线 段落 空行 结尾两个空格 区域引用 每行> 每段> 可嵌套 目录 把文档中所有标 ...

  10. 第4讲 | DHCP与PXE:IP是怎么来的,又是怎么没的?

    第4讲 | DHCP与PXE:IP是怎么来的,又是怎么没的? linux 配置网络IP地址: 使用 net-tools: sudo ifconfig eth1 10.0.0.1/24 sudo ifc ...