看了 why大佬的 博客一个困扰我122天的技术问题,我好像知道答案了。

发现他留了个坑,在变量i类型为 int 或者 Integer 时,int类型的i死循环了而Integer类型的i可以结束

int类型的i,出现死循环的机会是随机的,可能需要多来几次,估计1000来次吧

代码在下面,各位大佬可以拿去测测

public class VolatileDemo {
private static boolean flag = false;
private static int i = 0;
// (3)
// private static Integer i = 0;
// (4)
// private volatile static int i = 0; public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
// try {
// TimeUnit.MILLISECONDS.sleep(100);
flag = true;
// System.out.println("flag 被修改成 true");
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}).start();
while (!flag) {
i++;
// (1)
// System.out.println("flag标识 = " + flag);
// (2)
// try {
// TimeUnit.MILLISECONDS.sleep(10);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
System.out.println("程序结束,i=" + i);
} }

当时考虑的问题是 int 类型在栈上而 Integer 类型出现在堆上,一个普通类型另一个引用类型,在群里一阵讨论

最后在一个群友提示下发现了问题的关键,Integer 底层的 value用了 final修饰

final修饰变量,看过《java并发编程艺术》应该知道,它专门对final做了一个大章节的说明

最最重要的是它会添加内存屏障storestore,问题看起来是解决了

但新的问题出现了,还是看过《java并发编程艺术》的都知道,x86对写写,读写,读读内存屏障默认忽略,只对storeload有效

书本上又说道既然它加了storestore,x86无视它,那么为啥final会生效呢???

此处@why大佬过来讨论讨论到底怎么回事?

final添加内存屏障问题的更多相关文章

  1. 【C#】通过一个案例 彻底了解 Volatile和 内存屏障

    案例如下的.我个人理解是不会出现出现0,0的结果,但是很明显出现了. 说明对我对 Volatile\内存屏障\乱序排序的理解是不对. 今天就通过这个案例,理清这些概念. using System; u ...

  2. Java内存模型(MESI、内存屏障、volatile和锁及final内存语义)

    JMM (Java内存模型) Java线程的实现 实现线程主要有三种方式,Java线程从JDK1.3后采用第一种方式实现: 使用内核线程实现(1:1实现) 使用用户线程实现(1:N实现) 使用用户线程 ...

  3. JVM内存模型、指令重排、内存屏障概念解析

    在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...

  4. synchronized 与 volatile 原理 —— 内存屏障的重要实践

    单例模式的双重校验锁的实现: 第一种: private static Singleton _instance; public static synchronized Singleton getInst ...

  5. JVM内存模型、指令重排、内存屏障概念解析(转载)

    在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...

  6. [面试]volatile类型修饰符/内存屏障/处理器缓存

    volatile类型修饰符 本篇文章的目的是为了自己梳理面试知识点, 在这里做一下笔记. 绝大部分内容是基于这些文章的内容进行了copy+整理: 1. http://www.infoq.com/cn/ ...

  7. Java多线程学习笔记之三内存屏障与Java内存模型

    基本内存屏障 处理器支持那种内存重排序,就会提供能够禁止相应内存重排序的的指令,这些指令就被成为基本内存屏障:StroeLoad屏障.StroeLoad屏障.LoadLoad屏障.LoadStore屏 ...

  8. Linux内核中锁机制之内存屏障、读写自旋锁及顺序锁

    在上一篇博文中笔者讨论了关于原子操作和自旋锁的相关内容,本篇博文将继续锁机制的讨论,包括内存屏障.读写自旋锁以及顺序锁的相关内容.下面首先讨论内存屏障的相关内容. 三.内存屏障 不知读者是是否记得在笔 ...

  9. 大话Linux内核中锁机制之内存屏障、读写自旋锁及顺序锁

    大话Linux内核中锁机制之内存屏障.读写自旋锁及顺序锁 在上一篇博文中笔者讨论了关于原子操作和自旋锁的相关内容,本篇博文将继续锁机制的讨论,包括内存屏障.读写自旋锁以及顺序锁的相关内容.下面首先讨论 ...

随机推荐

  1. Boostrap bootstrap-table插件使用教程

    bootstrap table 简介及特性 简介 Bootstrap table 是国人开发的一款基于 Bootstrap 的 jQuery 表格插件,通过简单的设置,就可以拥有强大的单选.多选.排序 ...

  2. struct位域

    1 总结下 结构体位域的使用 比如  则 struct _COM2 { u8 Len : 1;//低位 u8 EoN : 2; u8 Stop:1; u8 Bps:4;//高位 } union COM ...

  3. 使用Python检测局域网内IP地址使用情况

    来源:https://www.cnblogs.com/donlin-zhang/p/6812675.html 在测试环境搭建的过程中,经常需要给服务器分配静态IP地址,由于不清楚当前局域网内部哪些IP ...

  4. Jquery ajax 详解(Day_16)

    太在意别人的看法最后会有两种结局,要么自己累死,要么让别人整死. 简介 AJAX 是与服务器交换数据的技术,它在不重载全部页面的情况下,实现了对部分网页的更新. 简短地说,在不重载整个网页的情况下,A ...

  5. IntelliJ IDEA配置tomcat 教程

    1.点击Run-Edit Configurations... 2.点击左侧"+",选择Tomcat Server--Local 3.在Tomcat Server -> Unn ...

  6. java为什么是一次编译,多次解释

    在编程语言中分为编译型语言.解释型语言,而我们的java语言既是编译型的也是解释型的,因为比如c语言是编译型的,因为我们将c语言的源代码编译过后就形成了.exe文件,这样windows系统就可以直接运 ...

  7. XShell本地上传文件到Ubuntu上及从Ubuntu下载文件到本地

    使用XShell本地上传文件到Ubuntu上及从Ubuntu下载文件到本地. 1.第一种方法是最常用的 :如果下载了Xshell和Xftp,Ctrl+Alt+F就可以选择文件的互传了!(虚拟机/云服务 ...

  8. JDBC使用详解

    第1章:JDBC概述 1.1 数据的持久化 持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用.大多数情况下,特别是企业级应用,数据持久化意味着将内存中的数据保存到硬盘上加以 ...

  9. 【补档_STM32单片机】脉搏波采集显示硬件设计

    一.脉搏波简介 ​ 脉搏一般情况下指的都是动脉脉搏.每分钟的脉搏次数称为脉率,正常情况下与心率是一致的.心脏的一次收缩和舒张成为一个心动周期.在每个心动周期内,心室的收缩和舒张会引起脉内压力的周期性波 ...

  10. Go benchmark 详解

    前言 基准测试(benchmark)是 go testing 库提供的,用来度量程序性能,算法优劣的利器. 在日常生活中,我们使用速度 m/s(单位时间内物体移动的距离)大小来衡量一辆跑车的性能,同理 ...