volatile

[JUC第一天]浅谈volatile关键字

馋奶兔 提交于 2020-03-08 10:09:38
文章目录 概述 可见性 为什么有时会不可见 如何解决 防止重排序 一个有趣的例子 重排序会导致什么 内存屏障 原子性 什么是原子性 volatile变量不具有原子性 概述 在Java语言规范第三版中, volatile 关键词的定义如下: Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地使用和更新,线程应该确保通过排他锁单独获得这个变量 并发编程中有两个很常见的关键词: synchronized 和 volatile volatile 可以用来修饰一个变量,使得并发情况下所有线程得到这个对象的值都是一样的 相比与 synchronized 操作会找个东西当锁, volatile 则是通过实时共享变量的值的方式来保证变量的可见性的,而并没有锁什么东西,所以说他的使用并不会引起程序的上下文切换,所以也说,volatile是轻量级的synchronized volatile最大的两个特点就是: 使得内存模型中所有线程获取到的值都是统一的(可见性) 避免指令在执行的时候因为优化机制重排序而出错 可见性 内存可见性 :每一个工作线程看到的某个变量的值都是相同的,而且是他最新的状态 为什么有时会不可见 这首先就要从计算机的缓存说起了: 很久以前,计算机的CPU和内存是直接连着的,但是这样导致的是传输速度跟不上CPU的运算速度 后来的计算机中通过设置缓存的方式

java中volatile关键字的含义

老子叫甜甜 提交于 2020-03-07 23:59:19
转: java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉。 Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制。 synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰的方法 或者 代码块。 volatile 用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。volatile很容易被误用,用来进行原子性操作。 下面看一个例子,我们实现一个计数器,每次线程启动的时候,会调用计数器inc方法,对计数器进行加一 执行环境——jdk版本:jdk1.6.0_31 ,内存 :3G cpu:x86 2.4G 1 public class Counter { 2 3 public static int count = 0; 4 5 public static void inc() { 6 7 //这里延迟1毫秒,使得结果明显 8 try { 9 Thread.sleep(1); 10 } catch

ConcurrentHashMap 的实现原理

若如初见. 提交于 2020-03-07 08:57:19
概述 我们在之前的博文中了解到关于 HashMap 和 Hashtable 这两种集合。其中 HashMap 是非线程安全的,当我们只有一个线程在使用 HashMap 的时候,自然不会有问题,但如果涉及到多个线程,并且有读有写的过程中,HashMap 就不能满足我们的需要了(fail-fast)。在不考虑性能问题的时候,我们的解决方案有 Hashtable 或者Collections.synchronizedMap(hashMap),这两种方式基本都是对整个 hash 表结构做锁定操作的,这样在锁表的期间,别的线程就需要等待了,无疑性能不高。 所以我们在本文中学习一个 util.concurrent 包的重要成员,ConcurrentHashMap。 ConcurrentHashMap 的实现是依赖于 Java 内存模型,所以我们在了解 ConcurrentHashMap 的前提是必须了解Java 内存模型。但 Java 内存模型并不是本文的重点,所以我假设读者已经对 Java 内存模型有所了解。 ConcurrentHashMap 分析 ConcurrentHashMap 的结构是比较复杂的,都深究去本质,其实也就是数组和链表而已。我们由浅入深慢慢的分析其结构。 先简单分析一下,ConcurrentHashMap 的成员变量中,包含了一个 Segment 的数组( final

The need for volatile modifier in double checked locking in .NET

耗尽温柔 提交于 2020-03-07 05:35:35
问题 Multiple texts say that when implementing double-checked locking in .NET the field you are locking on should have volatile modifier applied. But why exactly? Considering the following example: public sealed class Singleton { private static volatile Singleton instance; private static object syncRoot = new Object(); private Singleton() {} public static Singleton Instance { get { if (instance == null) { lock (syncRoot) { if (instance == null) instance = new Singleton(); } } return instance; } }

The need for volatile modifier in double checked locking in .NET

不羁的心 提交于 2020-03-07 05:33:09
问题 Multiple texts say that when implementing double-checked locking in .NET the field you are locking on should have volatile modifier applied. But why exactly? Considering the following example: public sealed class Singleton { private static volatile Singleton instance; private static object syncRoot = new Object(); private Singleton() {} public static Singleton Instance { get { if (instance == null) { lock (syncRoot) { if (instance == null) instance = new Singleton(); } } return instance; } }

多线程笔记:同步机制(1)

有些话、适合烂在心里 提交于 2020-03-07 00:22:25
同步机制简介 线程同步机制是一套用于协调线程间的数据访问及活动的机制,该机制用于保障线程安全以及实现这些线程的共同目标。 线程同步机制是编程语言为多线程运行制定的一套规则,合理地运用这些规则可以很大程度上保障程序的正确运行。 这套机制包含两方面的内容,一是关于多线程间的数据访问的规则,二是多线程间活动的规则。前者关乎程序运行的正确与否,是相当重要的内容;后者很大程度上是影响程序的运行效率,也是不容忽视的内容。不太严谨地说,数据访问的规则主要是由锁来实现,线程间活动的规则则表现线程调度上。 锁 线程安全问题的产生前提是多个线程并发访问共享数据,那么一种保障线程安全的方法就是将多个线程对共享数据的并发访问转换为串行访问,即一个共享数据一次只能被一个线程访问,该线程访问结束后其他线程才能对其进行访问。锁就是利用这种思路来实现线程同步机制。 GoLang中换了个思路,通过通道(channel)来实现共享数据的安全性。 锁的相关概念 锁在编程里是个蛮有趣的概念。 锁:置于可启闭的器物上,以钥匙或暗码(如字码机构、时间机构、自动释放开关、磁性螺线管等)打开的扣件 —— 在线新华字典 特定代码的作用域或是 lock() 和 unlock() 方法之间的代码构成的区域就是“器物”的表征,线程访问其中的共享数据相当于解开“扣件”,打开了“器物”;通常所说“获得xx锁”,更像是获得了“钥匙或暗码

Java多线程的基本知识

旧时模样 提交于 2020-03-06 18:54:17
1、进程与线程 进程是指一个程序的执行过程,持有资源和线程 线程是系统中最小的执行单元,一个进程可以有多个线程,线程共享进程资源,具有同步(线程的协作)与互斥(资源的争抢) 例如:我们一个班级当做一个进程,班级里面的学生就是线程,里面的学习工具就是资源,学生们的相互协作与竞争就是线程之间的同步与互斥 2、java对线程的支持 Thead类及Runnable接口 Runnable用来定义任务 Thead控制任务执行 Runnable可以避免Thread方式由于java单继承的特性带来的缺陷,可以被多个线程(Thread实例)共享,适合于多个线程处理同一个资源的情况。 class MyThread extends Thread{ @Override public void run() { } } MyThread mt = new MyThread(); mt.start();lass MyThread implements Runnable { public void run() { }}MyThread myThread = new MyThread();Thread td = new Thread(myThread);td.start(); 3、线程的生命周期 其中阻塞事件包括:sleep、 yield、 join、wait 阻塞解除:等待或休眠时间到了 notify

JUC

倾然丶 夕夏残阳落幕 提交于 2020-03-06 18:29:45
volatile 关键字和内存可见性: 内存可见性(Memory Visibility)是指当①某个线程正在使用对象状态,而②另一个线程在同时修改该状态,需要③确保当一个线程修改了对象 状态后,④其他线程能够看到发生的状态变化。----- 在程序运行的时候,jvm会为每个线程分配一块独立的缓存,其中有一块主存(存放着共享资源),线程一用于修改共享数据,main线程用于读共享数据, 当线程一要对主存中共享数据的值进行改变的时候,先把共享数据读到缓存中来,然后在修改值,修改完后,将修改好后的值写会到主存中去, 在将修改后的值写入主存中前,此时main线程从主存中的数据读取出来,按理来说是先线程一执行修改数据,在main线程读取修改后的数据, 由于在线程一共享数据写入主存之前就执行main线程中读取共享数据,所以导致main线程缓存中的值是修改前的值(按代码逻辑来说是修改后的), 此时main线程缓存中存放的值是修改前的值,当调用了比较底层的代码(例如while(true)),执行效率非常高,高到main线程没有机会再次去主存中 读取一次数据(就是线程一修改后的,即逻辑正确情况)。 内存可见性问题是,当多个线程操作共享数据时,彼此不可见(由于首先读取线程的数据(共享数据)是不符合代码逻辑的,再加上某个底层代码执行效率太高,读取线程无法再次去主存中获取最新数据)

volatile

心不动则不痛 提交于 2020-03-06 13:43:05
volatile并不是用来解决多线程竞争问题的,而是用来修饰一些因为程序不可控因素导致变化的变量,比如访问底层硬件设备的变量,以提醒编译器不要对该变量的访问擅自进行优化。 int fun(int& a) { int b = a; int c = a; return a+b+c; } int main() { int a=1; //.........做一些和a无关的事 return fun(a); } 作者:KE meng 链接:http://www.zhihu.com/question/31459750/answer/52061391 来源:知乎 著作权归作者所有,转载请联系作者获得授权。    这个代码是很好优化的,因为编译器知道a的值是1,参考上下文,编译器又能知道b和c的值也是1, 而且根本没有人用到了a,b,c三个变量,也没有任何人在修改a,b,c三个的值,所以编译器可能就直接 把这个函数优化成: int main() { return 3; } 了. 这么优化有什么问题吗? 单线程没问题,但多线程就有问题了,如果是多线程, a的值虽然在当前上下文中不会被修改,但可能正在被其他线程修改啊.于是上面的优化 就不对了. 那么,volatile关键字在这里就可以帮助我们了,volatile关键字提醒编译器: a可能随时被 意外 修改. 意外的意思是虽然当前这段代码里看起来a不会变

volatile与synchronized使用比较

烈酒焚心 提交于 2020-03-06 13:38:44
volatile英文含义【易变的】其实就是告诉CPU使用前必须重新去取值。 volatile比synchronized轻量级,不会造成阻塞,但是只实现了部分synchronized的功能。 volatile能保证可见性和有序性。但是保证不了原子性。synchronized可见性、有序性、原子性都可以保证。 来源: oschina 链接: https://my.oschina.net/u/3866531/blog/1939115