关于c中volatile关键字
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量
回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。
假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
1). 一个参数既可以是const还可以是volatile吗?解释为什么。
2). 一个指针可以是volatile 吗?解释为什么。
3). 下面的函数有什么错误:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:
1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
3). 这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
Volatile 关键字告诉编译器不要持有变量的临时性拷贝。一般用在多线程程序中,以避免在其中一个线程操作该变量时,将其拷贝入寄存器。请看以下情形:
A线程将变量复制入寄存器,然后进入循环,反复检测寄存器的值是否满足一定条件(它期待B线程改变变量的值。
在此种情况下,当B线程改变了变量的值时,已改变的值对其在寄存器的值没有影响。所以A线程进入死循环。
volatile 就是在此种情况下使用。
What does volatile do?
This is probably best explained by comparing the effects that volatile and synchronized have on a method. volatile is a field modifier, while synchronized modifies code blocks and methods. So we can specify three variations of a simple accessor using those two keywords:
int i1; int geti1() {return i1;}
volatile int i2; int geti2() {return i2;}
int i3; synchronized int geti3() {return i3;}
geti1() accesses the value currently stored in i1 in the current thread. Threads can have local copies of variables, and the data does not have to be the same as the data held in other threads. In particular, another thread may have updated i1in it's thread, but the value in the current thread could be different from that updated value. In fact Java has the idea of a "main" memory, and this is the memory that holds the current "correct" value for variables. Threads can have their own copy of data for variables, and the thread copy can be different from the "main" memory. So in fact, it is possible for the "main" memory to have a value of 1 for i1, for thread1 to have a value of 2 for i1 and for thread2 to have a value of 3 for i1 if thread1 and thread2 have both updated i1 but those updated value has not yet been propagated to "main" memory or other threads.
On the other hand, geti2() effectively accesses the value of i2 from "main" memory. A volatile variable is not allowed to have a local copy of a variable that is different from the value currently held in "main" memory. Effectively, a variable declared volatile must have it's data synchronized across all threads, so that whenever you access or update the variable in any thread, all other threads immediately see the same value. Of course, it is likely that volatile variables have a higher access and update overhead than "plain" variables, since the reason threads can have their own copy of data is for better efficiency.
Well if volatile already synchronizes data across threads, what is synchronized for? Well there are two differences. Firstlysynchronized obtains and releases locks on monitors which can force only one thread at a time to execute a code block, if both threads use the same monitor (effectively the same object lock). That's the fairly well known aspect to synchronized. But synchronized also synchronizes memory. In fact synchronized synchronizes the whole of thread memory with "main" memory. So executing geti3() does the following:
- The thread acquires the lock on the monitor for object
this(assuming the monitor is unlocked, otherwise the thread waits until the monitor is unlocked). - The thread memory flushes all its variables, i.e. it has all of its variables effectively read from "main" memory (JVMs can use dirty sets to optimize this so that only "dirty" variables are flushed, but conceptually this is the same. See section 17.9 of the Java language specification).
- The code block is executed (in this case setting the return value to the current value of
i3, which may have just been reset from "main" memory). - (Any changes to variables would normally now be written out to "main" memory, but for
geti3()we have no changes.) - The thread releases the lock on the monitor for object
this.
So where volatile only synchronizes the value of one variable between thread memory and "main" memory, synchronized synchronizes the value of all variables between thread memory and "main" memory, and locks and releases a monitor to boot. Clearly synchronized is likely to have more overhead than volatile.
关于c中volatile关键字的更多相关文章
- 【转】java中volatile关键字的含义
java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...
- 转:java中volatile关键字的含义
转:java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...
- Java中Volatile关键字详解 (转自郑州的文武)
java中volatile关键字的含义:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 一.基本概念 先补充一下概念:J ...
- java中volatile关键字的含义
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...
- Java中Volatile关键字详解
一.基本概念 先补充一下概念:Java并发中的可见性与原子性 可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值, ...
- 详解C中volatile关键字
volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据.如果没有volatile关键字,则编译器可能优化读取和存储 ...
- java中volatile关键字的含义 (转载)
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...
- 深入解析Java中volatile关键字的作用
转(http://m.jb51.net/article/41185.htm)Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制 在java线 ...
- C/C++中volatile关键字详解 (转)
1. 为什么用volatile? C/C++ 中的 volatile 关键字和 const 对应,用来修饰变量,通常用于建立语言级别的 memory barrier.这是 BS 在 "The ...
- 关于Java中volatile关键字笔记
volatile通常被认为是一种轻量级的synchronized,字面上它表示易变的,在并发编程中,它保证了共享变量的可见性.所谓可见性指的是,某个线程对变量进行操作后,其他线程能够读取到操作后的最新 ...
随机推荐
- 位图(BitMap)索引
前段时间听同事分享,偶尔讲起Oracle数据库的位图索引,顿时大感兴趣.说来惭愧,在这之前对位图索引一无所知,因此趁此机会写篇博文介绍下位图索引. 1. 案例 有张表名为table的表,由三列组成,分 ...
- HTMLTestRunner美化
https://www.cnblogs.com/findyou/p/6925733.html 参考这个,美化的不错,进入了汉化,及加入了一些样式,
- 面试题:判断两个字符串是否互为回环变位(Circular Rotaion)
题干: 如果字符串 s 中的字符循环移动任意位置之后能够得到另一个字符串 t,那么 s 就被称为 t 的回环变位(circular rotation). 例如,ACTGACG 就是 TGACG ...
- JSP页面的基本结构 及声明变量
一.JSP页面的基本结构 在传统的HTML页面文件里增加Java程序片和JSP标签就构成了一个JSP页面文件. 一个JSP页面可由5种元素组合而成: 1.普通的HTML标记符 2.Jsp标签.如指令标 ...
- Android之——获取手机安装的应用程序
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47114331 前几篇有关Android的博文中.向大家介绍了几个项目中经常使用的有 ...
- python对象序列化或持久化的方法
http://blog.csdn.net/chen_lovelotus/article/details/7233293 一.Python对象持久化方法 目前为止,据我所知,在python中对象持久化有 ...
- iOS-国家代码选择功能github开源分享
三行代码集成国家区号选择功能 功能执行效果如图: 开源链接: https://github.com/qxuewei/XWCountryCode 用法: 1.导入XWCountryCode类 2.在须要 ...
- php中利用reset,current,next和each,list来遍历数组
1.利用for循环以及reset,current,next来遍历数组: $nums = array(11,22,33,44,55,66,77,88); for(reset($nums);current ...
- tcp/ip ---子网寻址
现在所有的主机都要求支持子网编址( RFC 950 [Mogul and Postel 1985]).不是把I P地址看成由单纯的一个网络号和一个主机号组成,而是把主机号再分成一个子网号和一个主机号. ...
- angular4 radio checkbox 有用
<span *ngFor="let op of [{'id':'a','text':'11'},{'id':'b','text':'2222'},{'id':'cc','text':' ...