volatile

【Java并发编程】之五:volatile变量修饰符—意料之外的问题

耗尽温柔 提交于 2020-01-29 15:49:31
volatile用处说明 ​ 在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的。而随着JVM的成熟和优化,现在在多线程环境下volatile 关键字 的使用变得非常重要。 在当前的Java内存模型下, 线程 可以把 变量 保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个 变量 的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。 要解决这个问题,就需要把 变量 声明为volatile(也可以使用同步,参见 http://blog.csdn.net/ns_code/article/details/17288243 ),这就指示JVM,这个变量是不稳定的,每次使用它都到主存中进行读取。一般说来,多任务环境下,各任务间共享的变量都应该加volatile修饰符。 Volatile修饰的 成员变量 在每次被 线程 访问时,都强迫从 共享内存 中重读该成员变量的值。而且,当 成员变量 发生变化时,强迫线程将变化值回写到 共享内存 。这样在任何时刻,两个不同的线程总是看到某个 成员变量 的同一个值。 Java语言 规范中指出:为了获得最佳速度,允许线程保存共享 成员变量 的私有拷贝,而且只当线程进入或者离开 同步代码块 时才将私有拷贝与共享内存中的原始值进行比较。

Volatile and compiler optimization

耗尽温柔 提交于 2020-01-29 14:25:26
问题 Is it OK to say that 'volatile' keyword makes no difference if the compiler optimization is turned off i.e (gcc -o0 ....)? I had made some sample 'C' program and seeing the difference between volatile and non-volatile in the generated assembly code only when the compiler optimization is turned on i.e ((gcc -o1 ....). 回答1: No, there is no basis for making such a statement. volatile has specific semantics that are spelled out in the standard. You are asserting that gcc -O0 always generates code

Volatile and compiler optimization

你离开我真会死。 提交于 2020-01-29 14:25:07
问题 Is it OK to say that 'volatile' keyword makes no difference if the compiler optimization is turned off i.e (gcc -o0 ....)? I had made some sample 'C' program and seeing the difference between volatile and non-volatile in the generated assembly code only when the compiler optimization is turned on i.e ((gcc -o1 ....). 回答1: No, there is no basis for making such a statement. volatile has specific semantics that are spelled out in the standard. You are asserting that gcc -O0 always generates code

Java内存模型与线程

假如想象 提交于 2020-01-29 07:32:02
Java内存模型与线程 每秒事务处理数(Transactions Per Second,TPS)、 Java语言和虚拟机提供了许多工具,把并发编程的门槛降低了不少。另外,各种中间件服务器、各类框架 12.2 硬件的效率与一致性 现代计算机系统都不得不加入一层读写速度尽可能接近处理器运算速度的高速缓存(Cache)来作为内存与处理器之间的缓冲: 为了解决一致性的问题,需要各个处理器访问缓存时都遵循一些协议,在读写时要根据协议来进行操作,这类协议有MSI、MESI(IllinoisProtocol)、MOSI、Synapse、Firefly及Dragon Protocol,等等 为了使得处理器内部的运算单元能尽量被充分利用,处理器可能会对输入代码进行乱序执行(Out-Of-Order Execution)优化,处理器会在计算之后将乱序执行的结果重组,保证该结果与顺序执行的结果是一致的,类似,Java虚拟机的即时编译器中也有类似的指令重排序(Instruction Reorder)优化。 12.3 Java内存模型 用来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的并发效果。 12.3.1 主内存与工作内存 此处的变量包括了实例字段、静态字段和构成数组对象的元素,但是不包括局部变量与方法参数,因为后者是线程私有的[插图],不会被共享

volatile关键字

吃可爱长大的小学妹 提交于 2020-01-28 20:42:38
一、简介 volatile是Java提供的一种轻量级的同步机制。Java 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量,相比于synchronized(synchronized通常称为重量级锁),volatile更轻量级,因为它不会引起线程上下文的切换和调度。但是volatile 变量的同步性较差(有时它更简单并且开销更低),而且其使用也更容易出错。 二、并发编程的3个基本概念 (1)原子性 ​ 定义: 即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 ​ 原子性是拒绝多线程操作的,不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作。简而言之,在整个操作过程中不会被线程调度器中断的操作,都可认为是原子性。例如 a=1是原子性操作,但是a++和a +=1就不是原子性操作。Java中的原子性操作包括: ​ a. 基本类型的读取和赋值操作,且赋值必须是数字赋值给变量,变量之间的相互赋值不是原子性操作。 ​ b.所有引用reference的赋值操作 ​ c.java.concurrent.Atomic.* 包中所有类的一切操作 (2)可见性 ​ 定义: 指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。 ​ 在多线程环境下

Java中Volatile表示什么

我的梦境 提交于 2020-01-28 12:20:15
Java中volatile 修饰符是一种用来保证不同线程之间交互的特殊机制。当 一个线程修改volatile变量,另一个线程能够看到这个修改。第一个线程通知第二个线程变量已经被修改。 下面用图来解释: ready是一个volatile boolean变量, 初值设为false. answer是一个非volatile int变量,初值是0. 第一个线程准备好修改ready变量,它是两个线程交流的发送方。第二个线程读取ready变量,获取第一个线程修改的值,因此它是接收方。在两个线程交流时,在线程1修改ready变量前,内存中所有变量对线程1可见,在线程2准备好读取ready变量的值true后,内存中所有变量必须对线程2可见。 这就保证了如果线程要输出什么的值的话,那就是42. 如果ready不是volatile的,那会发生什么呢?在线程1和线程2之间将不会有任何明显的交流。 线程1修改ready(现在是non-volatile)后的值可能会传递给线程2,因此线程可能可以读取ready的值true. 然而,线程1也可能不会将修改后的ready的值传递给线程2,answer的值也不会传递给线程2,那么线程2将会输出0. 参考资料: http://jeremymanson.blogspot.jp/2008/11/what-volatile-means-in-java.html 来源:

错题0913-java

…衆ロ難τιáo~ 提交于 2020-01-28 11:42:29
1.下 列选项中关于Java中super关键字的说法正确的是() A.super关键字是在子类对象内部指代其父类对象的引用 B.super关键字不仅可以指代子类的直接父类,还可以指代父类的父类 C.子类通过super关键字只能调用父类的方法,而不能调用父类的属性 D.子类通过super关键字只能调用父类的属性,而不能调用父类的方法答案:A。解析: super是父类标识符,是子类对象内部指代父类对象的引用 super只可以指代子类的父类,不能指代父类的父类 可以通过super.xx来获取父类的变量(属性) 可以通过super.xx()来访问父类的方法 2. 多个线程可同时操作一个数据,为了保证该数据的准确性,可将操作该数据的部分改为 () A:同步 B:异步 C;只读 D:只写答案:A。解析: 1. 并发:在 操作系统 中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个 处理机 上运行。其中两种并发关系分别是同步和互斥 2. 互斥:进程间相互排斥的使用临界资源的现象,就叫互斥。 3. 同步: 进程之间的关系不是相互排斥临界资源的关系,而是相互依赖的关系。进一步的说明:就是前一个进程的输出作为后一个进程的输入,当第一个进程没有输出时第二个进程必须等待。具有同步关系的一组并发进程相互发送的信息称为消息或事件。 其中并发又有伪并发和真并发

volatile关键字是什么意思

喜你入骨 提交于 2020-01-28 00:25:38
我写了一段简单的对比代码并分别用vs2017以release方式编译然后用IDA观察汇编代码,如下图所示: 代码1 int a=5; printf("%d",a) 代码2 volatile int a =5; printf("%d",a); 左边是代码1的汇编代码,右边是代码2的汇编代码。 左边由于 编译器发现a的值是5,然后printf里面有一个a,然后根据等量代换直接就把a的值设置为5了。其实这是一种优化手段,能执行一句代码为什么要执行两句代码呢,是吧。 右边由于给a加上了volatile关键字,就是告诉编译器不要把这个变量优化掉了,该从哪里取数据就从哪里取数据。由于5这个数是存放在了[ebp-4]这个地址开始的内存单元处,所以传递参数的时候也是直接把这个地址的数据给传递进去了。 所以volatile关键字的意思就是 ,教练,请不要优化我啊。 来源: https://www.cnblogs.com/yfish/p/9692356.html

Java并发编程之volatile关键字解析

穿精又带淫゛_ 提交于 2020-01-28 00:23:45
Volatile和Synchronized四个不同点: 1, 粒度不同,前者锁对象和类,后者针对变量 2, syn线程阻塞,volatile线程不阻塞 3, syn保证三大特性,volatile不保证原子性 4, syn编译器优化,volatile不优化 volatile具备两种特性: 保证此变量对所有线程的可见性,指一条线程修改了这个变量的值,新值对于其他线程来说是可见的,但并不是多线程安全的。 禁止指令重排序优化。 Volatile如何保证内存可见性: 1.当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存。 2.当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。 同步:就是一个任务的完成需要依赖另外一个任务,只有等待被依赖的任务完成后,依赖任务才能完成。 异步:不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,只要自己任务完成了就算完成了,被依赖的任务是否完成会通知回来。(异步的特点就是通知)。 打电话和发短信来比喻同步和异步操作。 阻塞:CPU停下来等一个慢的操作完成以后,才会接着完成其他的工作。 非阻塞:非阻塞就是在这个慢的执行时,CPU去做其他工作,等这个慢的完成后,CPU才会接着完成后续的操作。 非阻塞会造成线程切换增加

Java多线程

99封情书 提交于 2020-01-27 05:11:11
一、停止线程(interrupt)   停止线程意味着在线程处理玩任务之前停掉正在做的操作,Java之前的版本提供Thread.stop()方法,但这个方法是不安全的,已被废弃。 1、目前停止线程主要有两种方式:   1)使用退出标志   2)使用interrupt方法中断线程。此方式需要使用interrupt对要中断的线程进行标记,通过interrupted或isInterrupted方法结合相应逻辑(break等操作)实现线程中断。 2、interrupt、interrupted、isInterrupted区别   1)interrupt标记线程为中断状态   2)interrupted测试当前线程是否中断,并清除中断标记为false   3)isInterrupted测试线程是否中断 3、使用interrupt方法中断线程实例 public class InterruptThread extends Thread { @Override public void run() { for(int i = 0; i < 50000; i++) { System.out.println("i = " + i); //if(this.isInterrupted()) { if(Thread.interrupted()) { System.out.println("thread stop