volatile

Should I synchronize a static volatile variable?

无人久伴 提交于 2020-01-22 19:40:13
问题 There are a few questions on this subject, but most skirt around this issue because it's not the intent of the question. If I have a static volatile in my class: private static volatile MyObj obj = null; and in a method below I do: public MyObj getMyObj() { if (obj == null) { obj = new MyObj();// costly initialisation } return obj; } will I need to synchronize to ensure only one thread writes to the field, or will any writes be immediately visible to other threads evaluating the obj == null

volatile之一--volatile不能保证原子性

家住魔仙堡 提交于 2020-01-22 05:44:04
目录: 《 Java并发编程之三:volatile关键字解析 转载 》 《 volatile之一--volatile不能保证原子性 》 《 Synchronized之一:基本使用 》 Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉。 Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制。 synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用synchronized 修饰的方法 或者 代码块。 volatile 用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。volatile很容易被误用,用来进行原子性操作。 下面看一个例子,我们实现一个计数器,每次线程启动的时候,会调用计数器inc方法,对计数器进行加一 执行环境——jdk版本:jdk1.6.0_31 ,内存 :3G cpu:x86 2.4G 复制代码 代码如下: public class Counter

ARM裸板开发——简单编写实现“shell”功能

谁说胖子不能爱 提交于 2020-01-21 12:44:56
文章目录 简单编写实现一个裸板环境下使用的“shell”功能程序,可以控制LED、beep等。 main主程序设计 主要函数:strcmp实现 LED初始化及控制功能实现 UART初始化及控制功能实现 使用Makefile编译 执行结果 简单编写实现一个裸板环境下使用的“shell”功能程序,可以控制LED、beep等。 main主程序设计 # include "uart.h" # include "strcmp.h" # include "led.h" //保存从上位机接收的数据信息 static char buf [ 32 ] ; void main ( void ) { //1.初始化UART uart_init ( ) ; //2.初始化LED led_init ( ) ; //3.根据用户需求完成业务 while ( 1 ) { uart_puts ( "\n Shell#" ) ; uart_gets ( buf , 32 ) ; if ( ! my_strcmp ( buf , "led on" ) ) led_on ( ) ; else if ( ! my_strcmp ( buf , "led off" ) ) led_off ( ) ; else uart_puts ( "\n Your command is invalid\n" ) ; } } 主要函数

volatile关键字的作用

巧了我就是萌 提交于 2020-01-20 17:45:29
引言   昨日接了一个阿里外包的电话面试,问了一些技术问题感觉到自己是真的菜,接触Java开发已经也有一段时间,技术方面说来惭愧,一直以来只是局限于框架工具的用法,也没有进行了解其实现的原理,更重要的是一直没有归纳和总结,这次把这些问题记录下来,相关的知识点也找了一些资料学习下。 问题 1. CountDownLanch的工作原理 实现原理:计数器的值由构造函数传入,并用它初始化AQS的state值。当线程调用await方法时会检查state的值是否为0,如果是就直接返回(即不会阻塞);如果不是,将表示该节点的线程入列,然后将自身阻塞。当其它线程调用countDown方法会将计数器减1,然后判断计数器的值是否为0,当它为0时,会唤醒队列中的第一个节点,由于CountDownLatch使用了AQS的共享模式,所以第一个节点被唤醒后又会唤醒第二个节点,以此类推,使得所有因await方法阻塞的线程都能被唤醒而继续执行。   引用别人的博客里的一段话,详细请点击: Java并发包中CountDownLatch的工作原理、使用示例 题外话: 什么是 AQS(抽象的队列同步器) AbstractQueuedSynchronizer类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问 共享资源的同步器框架,许多同步类实现都依赖于它,如常用的 ReentrantLock/Semaphore

并发编程系列之七多线程原子类AtomicInteger与不能保证原子性的volatile【原子在多线程下发生争抢】

会有一股神秘感。 提交于 2020-01-20 16:35:53
并发编程系列之七多线程原子类AtomicInteger与不能保证原子性的volatile【原子在多线程下发生争抢】,原子类都在JUC里面的Atomic包下面,包括所有的原子类,基本类的7个都有的,volatile【原子在多线程下发生争抢】,之所以不能保证原子性,主要是因为工作内存与线程内存在多线程的资源分布下,交互时volatile在刷新工作内存的时候没有保证线程的前后顺序。发生谁得到谁刷新,导致原子性,顺序上发生前后不一致,导致数据不一致。 示例1.volatile不能保证原子性,主要发生在多线程的情况下,如果线程只有一个原子性问题不存在,代码主要是volatile使用时,多个线程得到的结果不能得到结果10000就是问题,注意一定要有多个线程运行时,这个问题才能被发现。 import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.atomic.AtomicInteger; /** * Create on 2020年1月20日下午12:02:40 @author 脚踏实地,2020涅槃重生 * @version 1.0 * * @Description: 并发编程系列 */ public class AchieveSynObjectForVolatile extends

volitale 怎么保证可见性

醉酒当歌 提交于 2020-01-20 04:53:51
VOLATILE 只保证可见性,并不保证原子性 在说明Java多线程内存可见性之前,先来简单了解一下Java内存模型。 (1)Java所有变量都存储在主内存中 (2)每个线程都有自己独立的工作内存,里面 存该线程的使用到的变量副本(该副本就是主内存中该变量的一份拷贝) (1)线程对共享变量的所有操作都必须在自己的工作内存中进行,不能直接在主内存中读写 (2)不同线程之间无法直接访问其他线程工作内存中的变量,线程间变量值的传递需要通过主内存来完成。 线程1对共享变量的修改,要想被线程2及时看到,必须经过如下2个过程: (1)把工作内存1中更新过的共享变量刷新到主内存中 (2)将主内存中最新的共享变量的值更新到工作内存2中 可见性与原子性 可见性:一个线程对共享变量的修改,更够及时的被其他线程看到 原子性:即不可再分了,不能分为多步操作。比如赋值或者return。比如"a = 1;"和 "return a;"这样的操作都具有原子性。类似"a += b"这样的操作不具有原子性,在某些JVM中"a += b"可能要经过这样三个步骤: ① 取出a和b ② 计算a+b ③ 将计算结果写入内存 Synchronized:保证可见性和原子性 Synchronized能够实现原子性和可见性,在Java内存模型中,synchronized规定,线程在加锁时,先清空工作内存

Java多线程(5)

风格不统一 提交于 2020-01-19 18:35:07
Java多线程(5) CPU缓存一致性问题 因为缓存的出现,极大提高了CPU的吞吐能力,但同时也引入了缓存不一致的问题,比如i++操作 在程序运行过程,首先将主存中的数据复制一份存放到CPU Cache中,那么CPU寄存器进行数值计算的时候就直接到Cache中读取和写入,当整个运算过程完毕之后再讲Cache中的数据刷新到主存当中 具体如下: 读取主内存的i到cpu cache 对i进行+1操作 将结果写回到cpu cache中 将数据刷新到主内存 i++在单线程环境不会有什么问题,但在多线程下就会出现问题了 每个线程都有自己的工作内存,变量i会在多个线程的本地内存中都保存一个副本,如果同时两个线程执行i++操作,假设i的初始值为0,每一个线程都从主内存中获取i的值存入cpu cache,然后经过计算再写入主内存,很有可能i在经过了两次自增之后结果还是1,这就是典型的缓存不一致的问题 Java内存模型决定了一个线程对共享变量的写入何时对其他线程可见,Java内存模型定义了线程和主内存之间的抽象关系: 共享变量存储在主内存,每个线程都可以访问 每个线程都有私有的工作内存或者称为本地内存 工作内存只存储该线程对共享变量的副本 线程不能直接操作主内存,只有先操作了工作内存之后才能写入主内存 并发编程的三个重要特性 原子性 指在一次的操作或者多次操作中

5.volatile

假如想象 提交于 2020-01-19 09:20:34
文章目录 1. 并发开发中的变量不可见问题 1.1. 问题现象 1.2. 问题产生的原因 1.3. MESI MSI MOS Synapse Cache 一致性协议 2. 使用 volatile 解决变量不可见问题 3. volatile原理 3.1. volatile 的特性 3.2. volatile 的实现原则 3.3. volatile在字节码中的实现 3.4. volatile有序性的实现 1. 并发开发中的变量不可见问题 1.1. 问题现象 public class VolatileTest { public static boolean flag = false; public static void main(String[] args) throws InterruptedException { Thread threadA = new Thread(()->{ while (true) { if (flag) { System.out.println("ThreadA : flag is " + flag); break; } } System.out.println("ThreadA End"); }); Thread threadB = new Thread(()->{ flag = true; System.out.println("ThreadB :

Volatile总结

吃可爱长大的小学妹 提交于 2020-01-18 23:45:31
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉。 Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制。 synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰的方法 或者 代码块。 volatile 用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。volatile很容易被误用,用来进行原子性操作。 意思就是说,如果一个变量加了volatile关键字,就会告诉编译器和JVM的内存模型:这个变量是对所有线程共享的、可见的,每次jvm都会读取最新写入的值并使其最新值在所有CPU可见。 volatile似乎是有时候可以代替简单的锁,似乎加了volatile关键字就省掉了锁。但又说volatile不能保证原子性(java程序员很熟悉这句话:volatile仅仅用来保证该变量对所有线程的可见性,但不保证原子性) 。这不是互相矛盾吗? 1.Volatile不具有原子性 2.告诉jvm该变量为所有线程共享的,Cpu执行时不进行线程间上下文环境切换

volatile深度解析

南楼画角 提交于 2020-01-17 09:03:53
volatile深度解析 volatile是什么 volatile是Java虚拟机提供的 轻量级 的 同步机制 。它有三个特征: 保证可见性 不保证原子性 禁止指令重排 想要理解volatile的工作机制首先要了解JMM,java memory model,即java内存模型。 Java内存模型(JMM) JMM本身是一种抽象的概念,并不真实存在。它描述的是一组 规则或规范 ,通过这组规范定义了程序中各个 变量 (包括实例字段、静态字段和构成数组对象的元素)的 访问方式 。 注意,JMM只是一种规则,在java多线程情况下,如果 不做任何处理 ,每个线程都有自己的工作内存,如果访问主内存中的变量,将会从主内存中拷贝一份到工作内存,即使在某个线程的工作内存中做了修改, 没有刷新回主内存 ,那么对其他线程来说这个修改将是不可见的。具体如下图所示: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u6DHsKZd-1578637312474)(https://i.bmp.ovh/imgs/2019/06/5d19bc34bec03701.png)] 所以为了保证每个线程对主内存中的变量的修改对其他线程是可见的,就要引入volatile关键字。volatile不能保证原子性,但可以保证可见性和有序性(禁止指令重排)。 验证volatile可见性 class