volatile

How do I specify the equivalent of volatile in VB.net?

烂漫一生 提交于 2020-01-27 04:18:13
问题 I'm attempting to write a lock-free version of a call queue I use for message passing. This is not for anything serious, just to learn about threading. I'm relatively sure my code is correct, except if the instructions are re-ordered or done in registers. I know I can use memory barriers to stop re-ordering, but how can I ensure values are written to memory immediately? Public Class CallQueue Private first As New Node(Nothing) 'owned by consumer' Private last As Node = first 'owned by

Java关键字transient和volatile小结(转)

女生的网名这么多〃 提交于 2020-01-26 14:38:47
transient和volatile两个关键字一个用于对象序列化,一个用于线程同步,都是Java中比较高阶的话题,简单总结一下。 transient transient是类型修饰符,只能用来修饰字段。在对象序列化的过程中,标记为transient的变量不会被序列化。 示例: class Test { transient int a; // 不会被持久化 int b; // 持久化 } 当类Test的实例对象被序列化(比如将Test类的实例对象 t 写入硬盘的文本文件t.txt中),变量 a 的内容不会被保存,变量 b 的内容则会被保存。 参考: 把一个对象的表示转化为字节流的过程称为串行化(也称为序列化,serialization),从字节流中把对象重建出来称为反串行化(也称为为反序列化,deserialization)。transient 为不应被串行化的数据提供了一个语言级的标记数据方法。 volatile volatile 也是变量修饰符,只能用来修饰变量。volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变 化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。 在此解释一下Java的内存机制: Java使用一个主内存来保存变量当前值,而每个线程则有其独立的工作内存

并发专题(三)Volatile

这一生的挚爱 提交于 2020-01-26 10:10:41
Java语言规范第三版中对volatile的定义如下: java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致的更新,线程应该确保通过排他锁单独获得这个变量。 Volatile的定义和原理 Volatile是轻量级的Synchronized,比之执行成本更低,因为它不会引起线程的上下文切换,它在多处理器开发中保证了共享变量的“可见性”,“可见性”的意思是当一个线程修改一个变量时,另外一个线程能读到这个修改的值。Java语言提供了volatile,在某些情况下比锁更加方便。如果一个字段被声明成volatile,java线程内存模型确保所有线程看到这个变量的值是一致的。 package com.own.learn.concurrent.Volatile; public class VolatileBarrierExample { volatile Long v1 = null; public static void main(String[] args) { VolatileBarrierExample ex = new VolatileBarrierExample(); ex.readAndWrite(); } void readAndWrite() { v1 = 1L; } } JIT转化汇编代码:(v1变量) 0x00007f55cd100684: mov 0x20

Java 中终止线程的方法详解

被刻印的时光 ゝ 提交于 2020-01-26 10:08:47
Java中终止线程的方式主要有三种: 1、使用stop() 已被弃用。原因是:stop()是立即终止,会导致一些数据处理到一部分的时候就被终止,而用户并不知道哪些数据被处理,哪些数据没有被处理,产生了不完整的“残留”数据,不符合完整性,所以被废弃。 2、使用volatile标志位 下面来看一个例子:首先实现一个Runnable接口,在其中定义volatile标志位,在run()方法中使用标志位控制程序运行。 public class MyRunnable implements Runnable { //定义退出标志,true会一直执行,false会退出循环 //使用volatile目的是保证可见性,一处修改了标志,处处都要去主存读取新的值,而不是使用缓存 public volatile boolean flag = true ; public void run ( ) { System . out . println ( "第" + Thread . currentThread ( ) . getName ( ) + "个线程创建" ) ; try { Thread . sleep ( 1000 L ) ; } catch ( InterruptedException e ) { e . printStackTrace ( ) ; } //退出标志生效位置 while ( flag

面试-关键字

╄→гoц情女王★ 提交于 2020-01-26 09:52:12
一、请你讲讲Java里面的final关键字是怎么用的? 答:①final修饰一个类时,表示这个类不能被继承。final类中的成员变量可以根据需要设为final,但是要注意final类中的所有成员方法都会被隐式地指定为fianl方法。 ②使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义。第二个原因就是效率。在早期的Java实现版本中,会将fianl方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。 ②final修饰一个变量。如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。 二、请你谈谈关于Synchronized和lock? 答:synchronized是Java关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。 Lack是一个接口,而synchronized是java关键字,synchronized是内置的语言实现;synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象的发生;而Lock在发生异常时,如果没有主动通、过unlock()去释放锁,则很可能造成死锁现象

volatile关键字的用法

隐身守侯 提交于 2020-01-26 09:50:17
volatile关键字是在并发编程中使用频率非常高的一个关键字,那么volatile关键字到底有什么作用呢?根据官方的定义,volatile关键字主要有2个作用,保持变量在内存中的可见性和禁止指令重排序,下面就这2个用法进行详细的说明。 一、保持变量在内存中的可见性 要理解这句话首先要明白线程是怎么工作的,jvm运行时会给变量分配一个内存,我们可以称之为主内存,每一个线程运行时都会有一个线程栈,线程栈保存了线程运行时所需要用到的变量,这个变量就相当于主内存这个变量的副本一样,线程运行使用的是线程栈中的副本而不是主内存中的变量,在单线程中副本和主内存中的变量是一致的,但是在并发编程中就不一定了。 举个例子,有一个线程B要执行i=i+2的操作,线程A要执行i=i+1的操作,最后的结果应该是i=3,但是实际情况是i可能=1,因为线程B中i+2后i=2的值还没有写入到主内存,线程A也不知道i的值发生了变化,当线程A执行完i=0+1,最后i的值为1,然后写入到主内存,i的值为1,就像下图所示。 为了避免这个问题我们可以使用volatile关键字,使用volatile定义的变量i就不会出现这种情况,因为如果线程B修改了变量i的话,线程A就知道变量i的值发生了改变,就会使用修改过的值。如下图: 这就是volatile关键字可以使变量保证在内存中的可见性。 二、禁止指令重排序 什么是指令重排序

Volatile关键字

自作多情 提交于 2020-01-26 06:34:05
为什么会有这个关键字? 计算机在执行程序时,每条指令都是在 CPU 中执行的,而执行指令过程中,会涉及到数据的读取和写入,但由于 CPU 执行速度很快,而从内存读取数据和向内存写入数据的过程跟 CPU 执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度。因此在 CPU 里面就有了高速缓存。 也就是,当程序在运行过程中,会将运算需要的数据从主存复制一份到 CPU 的高速缓存当中,那么 CPU 进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数据刷新到主存当中。这样的操作在单线程中不会出现什么问题,但是在多线程中运行就可能会出现问题,会出现缓存不一致问题。所以在多线程的时候就需要加锁了,我们知道的在 CourrentHashMap 中是通过分段锁和 CAS 来实现线程安全的,这里面就涉及到了 Volatile 关键字。 并发编程的的三个概念(特性) 原子性 原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 一个很经典的例子就是银行账户转账问题: 比如从账户A向账户B转1000元,那么必然包括2个操作:从账户A减去1000元,往账户B加上1000元。 试想一下,如果这2个操作不具备原子性,会造成什么样的后果。假如从账户A减去1000元之后

Volatile作用

大兔子大兔子 提交于 2020-01-25 21:38:06
volatile的用处: 在JDK1.2之前,Java内存模型总是从主存(共享内存)中读取变量值,是不需要进行特别注意的。 在当前Java内存模型下,线程可以把变量保存在本地内存,如寄存器中,而不是直接在主存中进行读写。这就造成了一个线程在主存中修改了一个变量的值,而另一个线程还在使用它在寄存器中的变量值的拷贝,造成了了数据不一致。 为了解决这个问题,我们就需要把该变量声明为volatile,这就指示JVM,这个变量是不稳定的,每次使用他都要去主存中读取,而不是本地内存,一般说来,多任务环境下,各任务间共享的变量,都应该使用volatile进行修饰。 volatile修饰的变量,在被每次线程访问时,都强迫从共享内存中重读该变量的值。而且当该变量变化时,都强迫线程将变化的值写到共享内存中,这样在任何时刻,两个不同的线程总是看到该变量的同一个值。 Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才将私有拷贝与共享内存中的原始值进行比较。 这样当多个线程同时与某个对象交互时,就必须注意到要让线程及时的得到共享成员变量的变化。而volatile关键字就是提示JVM:对于这个成员变量,不能保存它的私有拷贝,而应直接与共享成员变量交互。 volatile是一种稍弱的同步机制,在访问volatile变量时不会执行加锁操作

Java中的volatile

别说谁变了你拦得住时间么 提交于 2020-01-25 00:39:38
目录 可见性保证 Happens-before 保证 volatile 并不能满足所有场景 什么时候单单使用 volatile 就够了? volatile 的性能考虑 Java的关键字 volatile 用于将变量标记为“存储于主内存中”。更确切地说,对 volatile 变量的每次读操作都会直接从计算机的主存中读取,而不是从 cpu 缓存中读取;同样,每次对 volatile 变量的写操作都会直接写入到主存中,而不仅仅写入到 cpu 缓存里。 实际上,从 Java 5 开始关键字 volatile 除了能确保 volatile 变量直接从主存中进行读写,还有以下几个作用。 可见性保证 关键字 volatile 能确保数据变化在线程之间的可见性。 在多线程的应用中多个线程对 non-volatile 变量进行操作,线程在对它们进行操作的时候为了提高性能会将变量从主存复制到 cpu 缓存中。如果你的电脑包含的 cpu 不止一个, 那么每个线程可能会运行于不同的 cpu 上。这意味着,不同线程会将变量复制到不同 cpu 的缓存里。如下图: no-volatile 变量不能保证 Java 虚拟机(JVM)何时从主存中将数据读入cpu 缓存,也不能保证何时将数据从 cpu 缓存写入到主存中。这会带来一些问题,我将在下面解释。 想象一个场景,两个或两个以上线程可访问同一个共享对象

第十一章多线程编程的硬件基础与Java内存模型

允我心安 提交于 2020-01-24 23:55:54
高速缓存内部结构示意图 缓存条目的结构 Data Block也被称为缓存行,它是高速缓存与主内存之间的数据交换最小单元,用于存储从主内存中读取或准备写往内存的数据。Tag则包含了与缓存行中数据相应的内存地址的部分信息(内存地址的高位部分比特)。Flag则用于表示响应缓存行的状态信息。 内存地址的解码结果包括tag、index以及offset三部分,index相当于桶号,tag相当于缓存条目的相对编号,offset是缓存行内的位置偏移。 MESI协议中一个缓存条目的Flag值有以下四种可能:Invalid(无效的,记为I)、shared(共享的,记为S),Exclusive(独占的,记为E)和Modified(更改过的,记为M)。 Processor 0读取数据S的实现 Processor 0写数据S的实现 写缓冲器 写缓冲器是处理器内部的一个容量比高速缓存还小的私有高速存储部件。一个处理器无法读取另外一个处理器的写缓冲器中的内容。 内存写操作的执行处理器在将写操作的相关数据写入写缓冲器之后便认为该写操作已经完成,一个处理器接收到其他处理器所回复的针对同一个缓存条目的所有Invalidate Acknowledge消息的时候,该处理器会将写缓冲器中针对相应地址的写操作的结果写入相应的缓冲行中。 无效化队列 引入无效化队列后