volatile

volatile

半城伤御伤魂 提交于 2020-01-07 21:54:18
volatile 关键字,使一个变量在多个线程间可见 mian,t1线程都用到一个变量,java默认是T1线程中保留一份副本,这样如果main线程修改了该变量, t1线程未必知道 使用volatile关键字,会让所有线程都会读到变量的修改值 volatile不能保证原子性举例 比如说第一个线程加到100了,还没往上加,另外一个线程来了,把100拿过来执行方法, 然后第一个线程继续加到101,第二个线程也加到101,他两往回写都是101,线程不会管你加到哪儿了, 虽然说加了2但是实际上只加了1. volatile并不能保证多个线程共同修改running变量时所带来的不一致问题, 也就是说volatile不能替代synchronized或者说volatile保证不了原子性 public class Demo { volatile int count = 0 ; public void test ( ) { for ( int i = 0 ; i < 10000 ; i ++ ) { count ++ ; } } public static void main ( String [ ] args ) { Demo demo = new Demo ( ) ; List < Thread > threads = new ArrayList < > ( ) ; for ( int i = 0

JAVA并发之volatile关键字

匆匆过客 提交于 2020-01-07 20:07:40
简介 volatile关键字可以说是Java虚拟机提供的最轻量级的同步机制,相对于synchronized,它只保证了变量可见性,没办法保证并发的正确性。Java内存模型对volatile专门定义了一些特殊的访问规则。它有两种特性,1.所有线程的可见性 2.禁止指令重排序优化。先记住这两个特性,首先说明下Java内存模型---JMM。 JMM Java虚拟机规范定义了一种Java内存模型---JMM来屏蔽各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。Java虚拟机规范定义了如下所示的JMM模型,其中工作内存是线程独有的,它会存储线程在运行过程中所用到的变量的主内存拷贝!(和基于高速缓存的存储交互式模型相似的) 主内存和工作内存之间的交互有具体的交互协议,JMM定义了八种操作来完成,这八种操作是原子的、不可再分的,它们分别是:lock,unlock,read,load,use,assign,store,write(具体作用请参考Java内存模型八个操作)。 接下来从顶到下的来介绍下volatile的工作原理。 volatile禁止指令重排序 首先对于定义的一个volatile变量,赋值后汇编代码会多执行一个"lock addl $0x0, (%exp)"操作,这个操作很关键 1、这个操作相当于一个内存屏障

Java并发(二)volatile

纵然是瞬间 提交于 2020-01-07 17:48:47
1. volatile的特性 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。( 实现可见性 ) 禁止进行指令重排序。( 实现有序性 ) volatile 只能保证对单次读/写的原子性。i++ 这种操作不能保证原子性。 2. Java内存模型 在Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽各个硬件平台和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。在此之前,主流程序语言(C/C++等)直接使用物理硬件和操作系统的内存模型(可以理解为类似于直接使用了硬件标准),都或多或少的在不同的平台有着不一样的执行结果。    Java内存模型的主要目标是定义程序中各个变量的访问规则,即变量在内存中的存储和从内存中取出变量这样的底层细节。其规定了所有变量都存储在主内存,每个线程还有自己的工作内存,线程读写变量时需先复制到工作内存,执行完计算操作后再回写到主内存,每个线程还不能访问其他线程的工作内存。大致示意图如下: 图三我们可以理解为和图二表达的是一个意思,工作内存可以看成是CPU高速缓存、寄存器的抽象,主内存可以看成就是物理硬件中主内存的抽象,图二这个模型会存在缓存一致性问题,图三同样也会存在缓存一致性问题。   另外,为了获得较好的执行性能

volatile底层原理

独自空忆成欢 提交于 2020-01-07 17:41:37
前言 我们知道volatile关键字的作用是保证变量在多线程之间的可见性,它是java.util.concurrent包的核心,没有volatile就没有这么多的并发类给我们使用。 本文详细解读一下volatile关键字如何保证变量在多线程之间的可见性,在此之前,有必要讲解一下CPU缓存的相关知识,掌握这部分知识一定会让我们更好地理解volatile的原理,从而更好、更正确地地使用volatile关键字。 CPU缓存 CPU缓存的出现主要是为了解决CPU运算速度与内存读写速度不匹配的矛盾 ,因为CPU运算速度要比内存读写速度快得多,举个例子: 一次主内存的访问通常在几十到几百个时钟周期 一次L1高速缓存的读写只需要1~2个时钟周期 一次L2高速缓存的读写也只需要数十个时钟周期 这种访问速度的显著差异,导致CPU可能会花费很长时间等待数据到来或把数据写入内存。 基于此,现在CPU大多数情况下读写都不会直接访问内存(CPU都没有连接到内存的管脚),取而代之的是CPU缓存,CPU缓存是位于CPU与内存之间的临时存储器,它的容量比内存小得多但是交换速度却比内存快得多。而缓存中的数据是内存中的一小部分数据,但这一小部分是短时间内CPU即将访问的,当CPU调用大量数据时,就可先从缓存中读取,从而加快读取速度。 按照读取顺序与CPU结合的紧密程度,CPU缓存可分为: 一级缓存:简称L1

15.uboot study 串口初始化

坚强是说给别人听的谎言 提交于 2020-01-07 16:41:50
3. 串口初始化 4. 代码实现 关于串口 对于嵌入式设备的开发,刚开始好多设备都无法使用,由于无法获得程序的运行状态,调试程序需要花费好多时间和精力,因此串口对于嵌入式程序的调试的作用显而易见,当串口不能用时,可能只能用led的亮灭来略微指示程序的运行状态,有了串口后,就能获得更多的调试信息了。S3C6410的串口使用和其它设备都差不多,初始化配置串口后,就可以收发数据了。首先来看下芯片手册上的串口框图: 串口信号线有发送数据信号线TXDn,接受数据信号线RXDn,如上图,这两根信号线分别连到了发送移位寄存器和接收移位寄存器,另外串口模块还包含了两个64Bytes的FIFO用来收发数据。除此外还有一个控制单元和波特率产生模块,相应的部分都被连到了系统的外围总线上面。 串口寄存器 先来看下相关的寄存器: S3C6410有UART0,1,2,3四个串口,上面只列出了串口0的相关寄存器,其他几个串口的寄存器说明和这个一样,下面来详细的说下: ###### ULCONx: 串口数据格式设置 数据长度,停止位长度 ,奇偶校验位 UCONx: 串口控制寄存器 选择时钟源,发送接收方式 UFCONx: FIFO控制寄存器 设置FIFO触发等级 使能 UTRSTATx: 发送接收状态寄存器 UERSTATx: 错误状态寄存器 帧错误,奇偶校验错误等 UFSTATx: FIFO 状态寄存器

并发编程的基石——CAS机制

爷,独闯天下 提交于 2020-01-07 11:29:35
本博客系列是学习并发编程过程中的记录总结。由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅。 并发编程系列博客传送门 Java中提供了很多原子操作类来保证共享变量操作的原子性。这些原子操作的底层原理都是使用了CAS机制。在使用一门技术之前,了解这个技术的底层原理是非常重要的,所以本篇博客就先来讲讲什么是CAS机制,CAS机制存在的一些问题以及在Java中怎么使用CAS机制。 其实Java并发框架的基石一共有两块,一块是本文介绍的CAS,另一块就是AQS,后续也会写博客介绍。 什么是CAS机制 CAS机制是一种数据更新的方式。在具体讲什么是CAS机制之前,我们先来聊下在多线程环境下,对共享变量进行数据更新的两种模式:悲观锁模式和乐观锁模式。 悲观锁更新的方式认为:在更新数据的时候大概率会有其他线程去争夺共享资源,所以悲观锁的做法是:第一个获取资源的线程会将资源锁定起来,其他没争夺到资源的线程只能进入阻塞队列,等第一个获取资源的线程释放锁之后,这些线程才能有机会重新争夺资源。synchronized就是java中悲观锁的典型实现,synchronized使用起来非常简单方便,但是会使没争抢到资源的线程进入阻塞状态,线程在阻塞状态和Runnable状态之间切换效率较低(比较慢)。比如你的更新操作其实是非常快的

Java容器的常见问题

为君一笑 提交于 2020-01-07 09:24:06
记录Java容器中的常见概念和原理 参考: https://github.com/wangzhiwubigdata/God-Of-BigData#%E4%B8%89Java%E5%B9%B6%E5%8F%91%E5%AE%B9%E5%99%A8 https://blog.csdn.net/justloveyou_/article/details/78653929 基础容器 ArrayList(动态数组)、LinkedList(带头结点的双向链表) ArrayList public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable 默认初始容量为 10; 扩容机制:添加元素前,先检查是否需要扩容,一般扩为源数组的 1.5 倍 + 1; 边界检查(即检查 ArrayList 的 Size):涉及到 index 的操作; 调整数组容量(减少容量):将底层数组的容量调整为当前列表保存的实际元素的大小; 在查找给定元素索引值等的方法中,源码都将该元素的值分为null和不为null两种情况处理; LinkedList LinkedList 不但实现了List接口,还实现了Dequeue接口。因此

多线程安全和内存模型

狂风中的少年 提交于 2020-01-07 08:42:26
同步 方法 使用 的是什么锁 ? synchronized 修饰方法使用锁是当前this锁。 synchronized 修饰静态方法使用锁是当前类的字节码文件 Threadlocal 什么是 Threadlocal ThreadLocal提高一个线程的局部变量,访问某个线程拥有自己局部变量。 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 实现原理: ThreadLoca通过map集合 Map.put(“当前线程”,值); J ava 内存模型 共享内存模型指的就是Java内存模型(简称JMM), JMM 决定一个线程对共享变量的写入时 ,能 对另一个线程可见 。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系: 线程之间的共享变量存储在主内存( main memory )中,每个线程都有一个私有的本地内存( local memory ),本地内存中存储了该线程以读 / 写共享变量的副本 。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。 什么是 J ava 内存模型: java 内存模型 简称 jmm , 定 义了 一个线程 对 另一个 线程可见。 共享 变量存放在主内存中

Java 多线程与并发(四):CAS

末鹿安然 提交于 2020-01-07 06:38:44
解决线程安全问题,除了上面的 Synchronized 锁之外还有另外一个应用特别广泛的知识点 CAS,可以说 JUC 包完全是建立在 CAS 的基础之上的。 定义 CAS,compare and swap ,是计算机科学中一种实现多线程原子操作的指令,它比较内存中当前存在的值和外部给定的期望值,只有两者相等时,才将这个内存值修改为新的给定值。 CAS操作包含三个操作数,需要读写的内存位置(V)、拟比较的预期原值(A)和拟写入的新值(B),如果V的值和A的值匹配,则将V的值更新为B,否则不做任何操作。 如何解决线程安全问题 前几篇文章多次强调线程安全需要解决的三个问题,原子性,可见性和重排序问题,我们来看看 CAS 能不能解决。 原子性:除了上文介绍的监视器(monitor)的实现,CAS 也能实现读取和更新的原子性操作。 可见性:使用 volatile 关键字来保证。 重排序:使用 volatile 关键字来保证。 所以 CAS + volatile 也能够保证线程安全。 原理 我们拿 AtomicInteger 来看看 CAS 如何在无锁的条件下保证数据的正确性。 private volatile int value; 首先对于我们要操作的变量,需要使用 volatile 关键字,用来保证线程之间的可见性以及防止重排序。这样获取变量的值时就能够直接读取。 public