volatile

C++中几个关键字

江枫思渺然 提交于 2020-02-18 04:50:49
volatile 编译优化时,为 提高存取速度 ,有时会把变量读取到寄存器,方便读取;但有时别的线程改变了变量的值,但寄存器值不变,造成程序读取值不一致,所以 使用volatile从变量内存中读取。 修饰某个变量,表明某个变量的值可能随时被外部改变,因此对这些变量的存取不能缓存到寄存器,每次使用时需要重新读取,从变量的地址中(内存中)读取数据。 volatile的作用 是告知编译器,它修饰的变量随时都可能被改变。因此,编译后的程序每次在使用该变量的值时,都会从 变量的地址中读取 数据,而不是从寄存器中获取。 作用:在进行编译时不优化,在执行的时候不缓存, 每次都需要从内存中读出(保证内存的可见性) 场景:多用于多线程或多CPU编程 static和const static和const static关键字至少有下列几个作用: (1)函数体内static变量的 作用范围为该函数体 ,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值; (2)在模块内的static全局变量可以被 模块内所用函数 访问,但不能被模块外其它函数访问; (3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的 使用范围被限制在声明它的模块内 ; (4)在类中的static成员变量属于 整个类所拥有 ,对类的所有对象只有一份拷贝; (5

最简单的STM32入门教程----闪烁LED

流过昼夜 提交于 2020-02-17 10:22:11
本文讲述的是如何从零开始,使用keil建立一个简单的STM32的工程,并闪烁LED灯,给小白看。 第零步 ,当然首先你得有一个STM32的板子,其IO口上接了一个LED。。。 第一步 ,建立一个文件夹0.0 第二步 ,打开keil,建立工程 在弹出来的对话框中选择你所用的STM32的芯片。 在接下来弹出来的对话框中选择是,这样keil就帮我们建立好了启动文件。 第三步 ,新建一个main.c文件,并添加到工程中。 点击New按钮,建立一个文本文件。 在建立的文本文件中输入C中的main函数 点击保存 保存后,将文件添加到工程中 第四步 ,点击编译 可以看到keil有报错 错误信息为: 没有定义的符号SystemInit ,这是因为在启动文件中有调用SystemInit函数,但是我们没有定义它,如下图: 暂时不用理会上述启动文件中汇编的含义,只需在main.c中添加该函数即可消除该错误。 修改后再编译,程序没有报错了。至此,一个STM32的工程就建立完成了。 第五步 ,将下面的代码复制粘贴 #define PERIPH_BASE ((unsigned int)0x40000000) #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) #define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) #define

并发编程之无锁

大憨熊 提交于 2020-02-16 21:03:53
并发编程之无锁 6.2 CAS与volatile 源码之LongAdder 6.8 Unsafe 6.2 CAS与volatile 其中的关键是compareAndSet,它的简称就是CAS(也有Compare And Swap的说法),它必须是原子操作。 注意 其实CAS的底层是lock cmpxchg指令(X86架构),在单核CPU和多核CPU下都能够保证【比较-交换】的原子性。 在多核状态下,某个核执行到带lock的指令时,CPU会让总线锁住,当这个核把此指令执行完毕,再开启总线。这个过程中不会被线程的调度机制所打断,保证了多个线程对内存操作的准确性,是原子的。 volatile 获取共享变量时,为了保证变量的可见性,需要使用volatile修饰。 它可以用来修饰成员变量和静态成员变量,他可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取它的值,线程操作volatile变量都是直接操作主存。即一个线程对volatile变量的修改,对另一个线程可见。 注意 : volatile仅仅保证了共享变量的可见性,让其它线程能够看到最新值,但不能解决指令交错问题(不能保证原子性) CAS必须借助volatile才能读取到共享变量的最新值来实现【比较并交换】的效果 为什么无锁效率高 无锁情况下,即使重试失败,线程始终在高速运行,没有停歇

volatile关键字

天大地大妈咪最大 提交于 2020-02-16 14:03:46
volatile的作用 阅读本篇前参见上一篇博文 https://www.cnblogs.com/dearnotes/p/12290564.html 1.保证此变量对所有线程的可见性 (当一条线程修改了这个变量的值,新值对于其他线程来说立即得知) 虽然是这样,但是我们并不能因此认为基于violate变量的运算在并发下是安全的。 public class VolatileTest extends Thread{ static volatile int increase = 0; static AtomicInteger aInteger=new AtomicInteger();//对照组 static void increaseFun() { increase++; aInteger.incrementAndGet(); } public void run(){ int i=0; while (i < 10000) { increaseFun(); i++; } } public static void main(String[] args) { VolatileTest vt = new VolatileTest(); int THREAD_NUM = 10; Thread[] threads = new Thread[THREAD_NUM]; for (int i = 0; i

技术之路你并不孤单,我与你同行

大憨熊 提交于 2020-02-16 03:22:56
Java提供多线程机制,在并发时以多个线程来处理每个请求的方式完成请求和响应。然而,广大程序员在实际编程时会遇到各种各样的问题和疑惑,在面对这些疑难杂症时,有的同学通过百度或谷歌迅速精准的搜索到解决方法,然后大功告成,在紧张的工作节奏中完成了领导交代的任务,待下次又出现这类问题时,再次百度或谷歌,如果哪天断网你还无法解决问题了!?我想说的是,一定要真正的理解问题背后的原因,比如线程死锁,到底是为何?是不是锁粒度大,多个资源被一个锁控制;系统响应慢,线程大量阻塞,是程序的哪块性能没优化好?或者是IO的影响,如果是IO瓶颈,你能分析出是网络IO还是磁盘IO,你是否考虑异步或者React模式实现?是否使用线程池?线程池的参数设置是否合理?锁的同步代码块是否可以考虑锁消除或缩小同步块范围? Java对我们来说,已经发展20多年的历史,现在诞生大量的框架,SSH SpringCloud Dubbo Shiro等。其实大量框架的催生,本质上都是以Java核心的技术为基础做了扩展和外延,所以掌握基础知识再学起框架会理解更加深刻,也能走的更久远。 我们都知道并发编程,在大型互联网公司用的特别多,高并发高流量给程序员带来巨大挑战。当然这是个整体方案,而不光是程序员能单独解决的。没有服务器扩容,没有高带宽,没有分布式集群部署,程序员使出浑身解数也无可救药!站在程序员角度,我们应该从基础学起

C语言/原子/编译,你真的明白了吗?

本秂侑毒 提交于 2020-02-14 04:24:06
  版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖。如要转贴,必须注明原文网址   http://www.cnblogs.com/Colin-Cai/p/7668982.html   作者:窗户   QQ:6679072   E-mail:6679072@qq.com   说到原子,类似于以下的代码可能人人都可以看出猫腻。 /* http://www.cnblogs.com/Colin-Cai */ #include <stdio.h> #include <pthread.h> int cnt = 0; void* mythread(void* arg) { int i; for(i=0;i<500000000;i++) cnt++; return NULL; } int main() { pthread_t id, id2; pthread_create(&id, NULL, mythread, NULL); pthread_create(&id2, NULL, mythread, NULL); pthread_join(id, NULL); pthread_join(id2, NULL); printf("cnt = %d\n", cnt); return 0; }   我想大多数人都知道其结果未必会得到1000000000。   测试一下吧。 linux

JVM学习(六):Java内存模型

假装没事ソ 提交于 2020-02-13 17:19:04
1、 Java内存模型 (Java Memory Model,JMM): 线程 、 主内存 和 工作内存 。所有的变量都存储在主内存(虚拟机内存的一部分)中,每条 线程 还有自己的 工作内存 。线程对变量的所有操作(读取、赋值等)必须在工作内存中进行,不同线程之间无法直接访问对方工作内存中的变量,需要通过主内存来完成。 2、如果要把一个变量从 主内存复制到工作内存 ,就要顺序地执行 read 和 load 操作,如果要把变量从 工作内存同步回主内存 ,就要顺序地执行 store 和 write 操作。 3、由于 volatile 变量只能保证可见性,不能保证原子性,为了保证线程并发的安全性,使用volatile时必须满足以下运算场景: (1)运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值。 (2)变量不需要与其他的状态变量共同参与不变约束。 4、Java内存模型是围绕着在并发过程中如何处理原子性、可见性和有序性来建立的: (1) 原子性 (Atomicity):基本数据类型的访问读写是具备原子性的(64位的long和double除外),如果需要更大范围的原子性保证,需要 lock 和 unlock 来操作,对应字节码指令 monitorenter 和 monitorexit ,对应Java代码中就是 sychronized 关键字。 (2) 可见性

java内存模型

孤街浪徒 提交于 2020-02-13 14:33:55
java内存模型 目的 java虚拟机通过试图定义一种java内存模型来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让java程序在各种平台下都能达到一致的内存访问效果。 实现方式 主内存和工作内存 1.所有变量存储在主内存中 2.工作内存保存了主内存的副本拷贝 3.线程对所有变量的操作(读取、赋值)都必须在工作内存中进行 4.线程减变量值得传递都必须通过主内存来完成 内存间交互操作 【lock】作用于主内存的变量,把一个变量标识为一条线程独占 【unlock】作用于主内存的变量,把一个锁定的变量释放出来 【read】作用于主内存的变量,把一个变量从主内存中读取出来以便随后的load使用 【load】作用于工作内存的变量,把read操作获取的变量放入工作内存的变量副本中 【use】作用于工作内存的变量,使用 【assign】作用于工作内存的变量,重新赋值 【store】作用于工作内存的变量,把变量的值传入到主内存中以便随后的write操作使用 【write】作用于主内存的变量 对于volatile型变量的特殊规则 volatile变量具有两种特性: 1.保证此变量对所有线程的可见性(如果一条线程改变了这个变量的值,新值对于其他线程是立即得知的) java的运算并非原子性的导致volatile变量的运算在并发出现不安全 2.禁止指令重排序优化 来源: https://www

必会,详细剖析11道嵌入式Linux C语言面试题

丶灬走出姿态 提交于 2020-02-13 00:43:15
预处理器(Preprocessor) 1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) 答: #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在这想看到几件事情: 1) #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等) 2) 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。 3) 意识到这个表达式将使一个16位机的整型数溢出, 因此要用到长整型符号L, 告诉编译器这个常数是长整型数。 4) 如果你在表达式中用到UL(表示无符号长整型),那么可能这就给面试者留下了很好的第一印象。记住第一印象很重要。 2 . 写一个"标准"宏MIN ,这个宏输入两个参数并返回较小的一个。 答: #define MIN(A,B) ((A) <= (B) ? (A) : (B)) 这个测试是为下面的目的而设的: 1) 标识#define在宏中应用的基本知识。这是很重要的。因为在 嵌入(inline)操作符 变为标准C的一部分之前,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。 2) 懂得在宏中小心地把参数用括号括起来 3) 我也用这个问题开始讨论宏的副作用,例如

关键字

半腔热情 提交于 2020-02-11 02:19:24
Synchronized 介绍 synchronized是Java实现同步的一种机制,它属于Java中关键字,是一种jvm级别的锁。synchronized锁的创建和释放是此关键字控制的代码的开始和结束位置,锁是由jvm控制的创建和释放的,正是因为这一点,synchronized锁不需要手动释放,哪怕是代码出现异常,jvm也能自动释放锁。 为什么要使用synchronized 在并发编程中存在线程安全问题,主要原因有:1.存在共享数据 2.多线程共同操作共享数据。关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile。 实现原理 synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性 应用方式 对于普通的同步方法: 锁是当前的对象 对于静态函数的同步方法: 锁是静态函数所在类的class对象 对于同步方法块的内容: 锁是指Synchonized括号里配置的对象 volatile Java程序中,为了提高程序运行效率,编译器会自动对其进行优化,把经常被访问的变量缓存起来,程序在读取变量时可能直接从缓存(例如寄存器)中来读取这个值,而不会从内存中取。但当遇到多线程编程时