volatile

Java内存模型原理

妖精的绣舞 提交于 2019-12-06 00:51:39
这篇文章主要介绍模型产生的问题背景,解决的问题,处理思路,相关实现规则,环环相扣,希望读者看完这篇文章后能对 Java 内存模型体系产生一个相对清晰的理解,知其然知其所以然。 内存模型产生背景 在介绍 Java 内存模型之前,我们先了解一下物理计算机中的并发问题,理解这些问题可以搞清楚内存模型产生的背景。 物理机遇到的并发问题与虚拟机中的情况有不少相似之处,物理机的解决方案对虚拟机的实现有相当的参考意义。 物理机的并发问题 硬件的效率问题 计算机处理器处理绝大多数运行任务都不可能只靠处理器“计算”就能完成,处理器至少需要与内存交互,如读取运算数据、存储运算结果,这个 I/O 操作很难消除(无法仅靠寄存器完成所有运算任务)。 由于计算机的存储设备与处理器的运算速度有几个数量级的差距,为了避免处理器等待缓慢的内存完成读写操作,现代计算机系统通过加入一层读写速度尽可能接近处理器运算速度的高速缓存。 缓存作为内存和处理器之间的缓冲: 将运算需要使用到的数据复制到缓存中,让运算能快速运行,当运算结束后再从缓存同步回内存之中。 缓存一致性问题 基于高速缓存的存储系统交互很好的解决了处理器与内存速度的矛盾,但是也为计算机系统带来更高的复杂度,因为引入了一个新问题:缓存一致性。 在多处理器的系统中(或者单处理器多核的系统),每个处理器(每个核)都有自己的高速缓存,而它们有共享同一主内存(Main

Java多线程与并发笔记

风流意气都作罢 提交于 2019-12-05 23:37:15
串行/并行/并发: https://www.cnblogs.com/goxcheer/p/9299181.html JMM: https://www.jianshu.com/p/8a58d8335270 JUC: https://www.cnblogs.com/linkworld/p/7819270.html https://www.cnblogs.com/q151860/p/8589683.html volatile是什么: https://blog.csdn.net/duqi_2009/article/details/94939145 volatile的作用: https://www.jianshu.com/p/2bbf4fcc74c0 volatile/static区别: https://www.cnblogs.com/huangjinyong/p/9540849.html NIO: https://www.jianshu.com/p/362b365e1bcc NIO/BIO/AIO: https://blog.csdn.net/guanghuichenshao/article/details/79375967 https://www.cnblogs.com/sxkgeek/p/9488703.html 来源: https://www.cnblogs.com/yyjh/p

Java基础之Volatile原理

无人久伴 提交于 2019-12-05 23:05:18
原文链接: http://www.aoaoyi.com/archives/956.html 计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据 的读取和写入。由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就 存在一个问题,由于CPU执行速度很快,而从内存读取数据和向内存写入数据的过程跟CPU 执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来 进行,会大大降低指令执行的速度。因此在CPU里面就有了高速缓存。当程序在运行过程 中,会将运算需要的数据从主存复制一份到CPU的高速缓存当中,那么CPU进行计算时就可 以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数 据刷新到主存当中。举个简单的例子,比如下面的这段代码: i = i + 1; 当线程执行这个语句时,会先从主存当中读取 i 的值,然后复制一份到高速缓存当中, 然后 CPU 执行指令对 i 进行加1操作,然后将数据写入高速缓存,最后将高速缓存 中 i 最新的值刷新到主存当中。 这个代码在单线程中运行是没有任何问题的,但是在多线程中运行就会有问题了。在多核 CPU 中,每条线程可能运行于不同的 CPU 中,因此 每个线程运行时有自己的高速缓存(对 单核CPU来说,其实也会出现这种问题,只不过是以线程调度的形式来分别执行的

java - volatile

ぃ、小莉子 提交于 2019-12-05 22:41:21
volatile主要用来使线程之间数据可见 不同线程操作同一个对象时,会先把对象复制一份给自己的运行内存然后操作完了再放回去。 如果两个线程一起操作对象,两者之间操作的对象其实不是同一个,而是各自拿到的主内存中的复制。 而volatile修饰的对象属性,会保证其可见性,使用这个属性时会同步到主内存,使其他线程知道。 volatile保证了对象属性的一致性,但是不保证原子性。有可能你这边改了一半,另一边已经又变了。。。 阿里面试题: 涉及一个容器,线程1往其中添加10个数字,线程二监控线程1,在其添加5个数字时停止。 import java.util.ArrayList; public class Vol { public volatile ArrayList<Integer> arr; public Vol(){ arr = new ArrayList<Integer>(); } public void add(int e){ arr.add(e); } public int size(){ return arr.size(); } } main public class test { public static void main(String[] args){ Vol v =new Vol(); Thread t1 = new Thread(){ public int stop

volatile原理与技巧--Java

白昼怎懂夜的黑 提交于 2019-12-05 21:24:39
为什么使用volatile比同步代价更低? 同步的代价, 主要由其覆盖范围决定, 如果可以降低同步的覆盖范围, 则可以大幅提升程序性能. 而volatile的覆盖范围仅仅变量级别的. 因此它的同步代价很低. volatile原理是什么? volatile的语义, 其实是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我.(工作内存详见java内存模型) 因此, 当多核或多线程在访问该变量时, 都将直接操作主存, 这从本质上, 做到了变量共享. volatile的有什么优势? 1, 更大的程序吞吐量 2, 更少的代码实现多线程 3, 程序的伸缩性较好 4, 比较好理解, 无需太高的学习成本 volatile有什么劣势? 1, 容易出问题 2, 比较难设计 volatile运算存在脏数据问题 volatile仅仅能保证变量可见性, 无法保证原子性. volatile的race condition示例: public class TestRaceCondition { private volatile int i = 0; public void increase() { i++; } public int getValue() { return i; } } 当多线程执行increase方法时, 是否能保证它的值会是线性递增的呢? 答案是否定的. 原因:

C语言中auto,register,static,const,volatile的区别

走远了吗. 提交于 2019-12-05 21:24:14
1)auto 这个关键字用于声明变量的生存期为自动,即将不在任何类、结构、枚举、联合和函数中定义的变量视为全局变量,而在函数中定义的变量视为局部变量。这个关键字不怎么多写,因为所有的变量默认就是auto的。 (2)register 这个关键字命令编译器尽可能的将变量存在CPU内部寄存器中而不是通过内存寻址访问以提高效率。 (3)static 常见的两种用途: 1>统计函数被调用的次数; 2>减少局部数组建立和赋值的开销.变量的建立和赋值是需要一定的处理器开销的,特别是数组等含有较多元素的存储类型。在一些含有较多的变量并且被经常调用的函数中,可以将一些数组声明为static类型,以减少建立或者初始化这些变量的开销. 详细说明: 1>、变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与栈变量和堆变量的区别。 2>、变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。 3>当static用来修饰全局变量时,它就改变了全局变量的作用域,使其不能被别的程序extern,限制在了当前文件里,但是没有改变其存放位置,还是在全局静态储存区。 使用注意: 1>若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度; 2>若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量

C语言中auto,register,static,const,volatile的区别

大憨熊 提交于 2019-12-05 21:23:35
1)auto   这个关键字用于声明变量的生存期为自动,即将不在任何类、结构、枚举、联合和函数中定义的变量视为全局变量,而在函数中定义的变量视为局部变量。这个关键字不怎么多写,因为所有的变量默认就是auto的。 (2)register   这个关键字命令编译器尽可能的将变量存在CPU内部寄存器中而不是通过内存寻址访问以提高效率。 (3)static   常见的两种用途:     1>统计函数被调用的次数;     2>减少局部数组建立和赋值的开销.变量的建立和赋值是需要一定的处理器开销的,特别是数组等含有较多元素的存储类型。在一些含有较多的变量并且被经常调用的函数中,可以将一些数组声明为static类型,以减少建立或者初始化这些变量的开销.   详细说明:     1>、变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与栈变量和堆变量的区别。     2>、变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。     3>当static用来修饰全局变量时,它就改变了全局变量的作用域,使其不能被别的程序extern,限制在了当前文件里,但是没有改变其存放位置,还是在全局静态储存区。   使用注意:     1>若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;   

Volatile关键字实现原理

故事扮演 提交于 2019-12-05 21:00:25
1、认识volatile关键字 程序举例 用一个线程读数据,一个线程改数据 存在数据的不一致性 2、机器硬件CPU与JMM (1)CPU Cache模型 程序的局部执行原理 (2)CPU缓存的一致性问题 解决方案: 1)总线加锁(粒度太大) 2)MESI() 读操作:不做任何事情,把Cache中的数据读到寄存器 写操作:发出信号通知其他的CPU讲改变量的Cache line置为无效,其他的CPU要访问这个变量的时候,只能从内存中获取。 Cache line CPU的cache中会增加很多的Cache line (3)Java内存模型 1) 主存中的数据所有线程都可以访问(共享数据) 2) 每个线程都有自己的工作空间,(本地内存)(私有数据) 3) 工作空间数据:局部变量、内存的副本 4) 线程不能直接修改内存中的数据,只能读到工作空间来修改,修改完成后刷新到内存 3、Volatile关键字的语义分析 volatile作用: 让其他线程能够马上感知到某一线程多某个变量的修改 (1) 保证可见性 对共享变量的修改,其他的线程马上能感知到 不能保证原子性 读、写、(i++) (2) 保证有序性 重排序(编译阶段、指令优化阶段) 输入程序的代码顺序并不是实际执行的顺序 重排序后对单线程没有影响,对多线程有影响 Volatile Happens-before volatile规则:

Why does the compiler optimize away shared memory reads due to strncmp() even if volatile keyword is used?

爷,独闯天下 提交于 2019-12-05 20:14:58
Here is a program foo.c that writes data to shared memory. #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <stdint.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/shm.h> int main() { key_t key; int shmid; char *mem; if ((key = ftok("ftok", 0)) == -1) { perror("ftok"); return 1; } if ((shmid = shmget(key, 100, 0600 | IPC_CREAT)) == -1) { perror("shmget"); return 1; } printf("key: 0x%x; shmid: %d\n", key, shmid); if ((mem = shmat(shmid, NULL, 0)) == (void *) -1) { perror("shmat"); return 1; } sprintf(mem, "hello"); sleep(10); sprintf(mem, "exit");

JAVA面试题汇总

◇◆丶佛笑我妖孽 提交于 2019-12-05 19:49:30
没有什么套路,就是直接上干货!!!最新Java面试题汇总整理连答案一块儿分享给大家,希望对大家有帮助~ 之后还会推出Java面试题系列文章,敬请关注! 按照技术模块:Java热点技术、多线程、微服务、JVM、Redis、消息队列、SQL相关的面试题。不要走开,稍后更精彩! 1、面向对象的特点有哪些? 抽象、继承、封装、多态。 2、接口和抽象类有什么联系和区别? 3、重载和重写有什么区别? 4、java有哪些基本数据类型? 5、数组有没有length()方法?String有没有length()方法? 数组没有length()方法,它有length属性。 String有length()方法。 集合求长度用size()方法。 6、Java支持的数据类型有哪些?什么是自动拆装箱? 7、int 和 Integer 有什么区别? 8、Java类的实例化顺序? 父类静态成员和静态代码块 -> 子类静态成员和静态代码块 -> 父类非静态成员和非静态代码块 -> 父类构造方法 -> 子类非静态成员和非静态代码块 -> 子类构造方法 9、什么是值传递和引用传递? 10、String能被继承吗?为什么? 11、String和StringBuilder、StringBuffer的区别? StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况(是线程不安全的) StringBuffer