我正在使用Microchip的编译器编写微控制器(dsPIC24).外围设备都是内存映射变量.偶尔有必要通过读取来清除缓冲区,我通常只做:
SPI1BUF;
Run Code Online (Sandbox Code Playgroud)
... 在Microchip的标题中SPI1BUF声明volatile char了哪里.它适用于我,但现在我很好奇:它是标准化的行为吗?我记得如果我执行任务:
unsigned char x = SPI1BUF;
Run Code Online (Sandbox Code Playgroud)
......标准说必须读取volatile变量.但对于标识符整体表达式情况,这也是如此吗?
我在某处读到x86处理器具有高速缓存一致性,并且可以在每次写入时同步多个内核的字段值.
这是否意味着如果我们计划仅在x86处理器上运行,我们可以在不使用java中的'volatile'keywoard的情况下进行编码?
更新:
好吧,假设我们忽略了指令重新排序的问题,我们是否可以假设在x86处理器上不存在对核心不可见的非易失性字段的分配问题?
查看JLabel的源代码我关注文本字段的可见性.我提取了必要部分来设置文本字段并检索oldValue.我认为如果String文本字段未声明为volatile,则可见性存在危险,因为firePropertyChange可能看不到之前由另一个线程保存的文本字段中检索到的oldValue.我是对的,还是我错过了什么?请注意,这不是讨论SwingUtility.
public class JLabel extends JComponent implements SwingConstants, Accessible {
...
private String text = ""; // "" rather than null, for BeanBox
...
public void setText(String text) {
String oldAccessibleName = null;
if (accessibleContext != null) {
oldAccessibleName = accessibleContext.getAccessibleName();
}
String oldValue = this.text;
this.text = text;
firePropertyChange("text", oldValue, text);
...
Run Code Online (Sandbox Code Playgroud)
提前谢谢了.
我在Sun的"Core Servlets和JavaServer Pages vol 2"中看到了一个带会话计数器的例子.
计数器只需构建,HttpSessionListener并使用sessionCreated/ 递增/递减会话计数sessionDestroyed:
public class SessionCounter implements HttpSessionListener {
private int currentSessionCount = 0;
public void sessionCreated(HttpSessionEvent event) {
currentSessionCount++;
}
...
public int getTotalSessionCount() {
return(totalSessionCount);
}
... // counter decrement, self registering in context attribute etc.
Run Code Online (Sandbox Code Playgroud)
监听器在上下文中注册自己,因此servlets可以访问它并获得计数器值.
没有同步块.
它安全吗,currentSessionCount不是volatile吗?
可以currentSessionCount缓存在CPU寄存器中,并且对于提供请求的其他线程的精确值是不可见的servlets?
volatile写入是否确保在一个线程中的任何写入(非易失性/易失性写入)在其他线程可见之前发生?
下面给出的代码总是会产生90,80输出吗?
public class MyClass
{
private boolean flag = false;
private volatile int volatileInt = 0;
private int nonVolatileInt = 0;
public void initVariables()
{
nonVolatileInt = 90; // non-volatile write
volatileInt = 80; // volatile write
flag = true; // non-volatile write
}
public void readVariables()
{
while (flag == false)
{}
System.out.println(nonVolatileInt + ","+ volatileInt);
}
public static void main(String st[])
{
final MyClass myClass = new MyClass();
Thread writer = new Thread( new Runnable() …Run Code Online (Sandbox Code Playgroud) 我有一个类从一个串行读取数据,具有高阈值(1个字节).
我有一个变量存储来自串口的所有数据:_dataReceived.
private volatile string _dataReceived;
Run Code Online (Sandbox Code Playgroud)
我正在使用DataReceived事件来存储这些数据,然后我开始一个动作来处理它.
private void _port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string newData = _port.ReadExisting();
_dataReceived += newData;
new Action(() =>
{
Debug("Data received: {0}", newData);
ParseAnswers();
}).BeginInvoke(null, null);
}
Run Code Online (Sandbox Code Playgroud)
处理它,包括从变量中删除它并处理答案.ParseAnswers方法如下所示:
private void ParseAnswers()
{
string cmd = null;
int idx = -1;
lock (_dataReceived)
{
idx = _dataReceived.IndexOf(Environment.NewLine);
if (idx != -1)
{
cmd = _dataReceived.Substring(0, idx);
_dataReceived = _dataReceived.Substring(idx + 2);
}
else
return;
}
...
}
Run Code Online (Sandbox Code Playgroud)
这有99.9%的时间.
但有时我会在这一行得到一个ArgumentOutOfRangeException:
cmd = _dataReceived.Substring(0, idx);
Run Code Online (Sandbox Code Playgroud)
现在,我的问题是:我的变量是volatile,这意味着我总是访问真正的值而不是缓存.我很确定我的DataReceived事件一直在增加(快速),但是我使用lock语句来阻止任何其他线程更改此值.如果没有在字符串中使用NewLine,就无法运行这段代码(子字符串).而且这个IndexOf无法从字符串中返回索引.
那么......这里到底发生了什么? …
我发现了这个声明,我想不出有什么理由.
当字段的值取决于其先前的值时,易失性不起作用
任何有关示例的解释都非常感谢.
从我在网上和SO上看到的内容:
常量:
挥发性:
如果我的理解是正确的,那么易变性只是另一种常量.
那么,像下面那样的线是什么意思呢?
const volatile char A = 'C';
如果未使用关键字指定变量volatile,则编译器可能会进行缓存。必须始终从内存访问该变量,否则直到其事务单元结束。我想知道的重点在于装配零件。
int main() {
/* volatile */ int lock = 999;
while (lock);
}
Run Code Online (Sandbox Code Playgroud)
在x86-64-clang-3.0.0编译器上,其汇编代码如下。
main: # @main
mov DWORD PTR [RSP - 4], 0
mov DWORD PTR [RSP - 8], 999
.LBB0_1: # =>This Inner Loop Header: Depth=1
cmp DWORD PTR [RSP - 8], 0
je .LBB0_3
jmp .LBB0_1
.LBB0_3:
mov EAX, DWORD PTR [RSP - 4]
ret
Run Code Online (Sandbox Code Playgroud)
当volatile关键字被注释时,结果如下。
main: # @main
mov DWORD PTR [RSP - 4], 0
mov DWORD …Run Code Online (Sandbox Code Playgroud) 我现在有一些代码希望在Teensy 3.6微控制器上的基于计时器的中断中运行。该代码访问类的[global]对象数组。我已经将该数组和所有成员变量标记为volatile,我认为这是正确处理中断的第一步。
我标记为volatile的成员变量之一是std :: bitset,我想称其为非易失性方法,我不能这样做
"passing 'volatile std::bitset<16u>' as 'this' argument discards qualifiers [-fpermissive]"
Run Code Online (Sandbox Code Playgroud)
我想我可以复制位集库并将所有内容切换为volatile,但是我认为这不是必需的,所以我认为有更好的解决方案,或者我在错误地考虑问题。
请让我知道应该怎么做。
这些答案似乎建议在ISR和多线程程序中访问ISR中的全局变量时使用volatile: C'Volatile'关键字?,
在中断例程中使用C ++对象(和volatile)的正确方法是什么?,
这是许多建议使用的外部资源的补充。也许我的原始信息不清楚,或者我的情况与此不同。
volatile ×10
java ×5
concurrency ×3
c ×2
c++ ×2
arduino ×1
assembly ×1
c# ×1
const ×1
counter ×1
interrupt ×1
locking ×1
non-volatile ×1
serial-port ×1
standards ×1
swing ×1
visibility ×1
x86-64 ×1