Luc*_*uca 34 c++ volatile while-loop
我正在看一个C++类,它有以下几行:
while( x > y );
return x - y;
Run Code Online (Sandbox Code Playgroud)
x并且y是类型的成员变量volatile int.我不明白这个结构.
我在这里找到了代码存根:https://gist.github.com/r-lyeh/cc50bbed16759a99a226.我想这不保证是正确的甚至是工作.
the*_*ker 62
由于x并且y已经被声明为volatile,程序员希望它们将从程序外部进行更改.
在这种情况下,您的代码将保留在循环中
while(x>y);
Run Code Online (Sandbox Code Playgroud)
并且将在值x-y从外部更改之后返回值x <= y.在您告诉我们有关您的代码的更多信息以及您看到它的位置之后,可以猜到写这个的确切原因.while在这种情况下,循环是一种等待其他事件发生的技术.
Sta*_*tas 25
它似乎
while( x > y );
Run Code Online (Sandbox Code Playgroud)
是一个旋转循环.它不会停止直到x <= y.由于x和y是volatile,他们可能这个例程之外被改变.所以,一旦x <= y成为现实,x - y将被退回.此技术用于等待某些事件.
更新
根据您添加的要点,似乎想法是实现线程安全的无锁循环缓冲区.是的,实施不正确.例如,原始代码片段是
unsigned count() const {
while( tail > head );
return head - tail;
}
Run Code Online (Sandbox Code Playgroud)
即使tail变得小于或等于head,也不能保证head - tail返回正数.调度程序可以在while循环之后立即将执行切换到另一个线程,并且该线程可以改变head值.无论如何,还有许多与读取和写入共享内存工作(内存重新排序等)有关的其他问题,所以请忽略此代码.
Syr*_*ran 20
其他回复已经详细指出了指令的作用,但只是回顾一下,因为y(或head在链接的例子中)被声明为volatile从不同的线程对该变量进行的更改将导致while循环一旦条件已经完成满足.
但是,即使链接代码示例非常短,它也是如何不编写代码的近乎完美的示例.
首先是线路
while( tail > head );
Run Code Online (Sandbox Code Playgroud)
将浪费大量的CPU周期,几乎锁定一个核心,直到满足条件.
随着我们的进展,代码变得更好.
buffer[head++ % N] = item;
Run Code Online (Sandbox Code Playgroud)
感谢JAB指出我错误的帖子 - 这里有预增量.纠正了影响.
由于没有locks或mutexes,我们显然必须承担最坏的情况.item在head++执行之前和之后分配值时,线程将切换.然后,Murphy将再次调用包含此语句的函数,item并在同一head位置指定值.之后head增加.现在我们切换回第一个线程并head再次递增.而不是
buffer[original_value_of_head+1] = item_from_thread1;
buffer[original_value_of_head+2] = item_from_thread2;
Run Code Online (Sandbox Code Playgroud)
我们最终得到了
buffer[original_value_of_head+1] = item_from_thread2;
buffer[original_value_of_head+2] = whatever_was_there_previously;
Run Code Online (Sandbox Code Playgroud)
你可能会在客户端使用很少的线程来摆脱这样的草率编码,但在服务器端,这只能被认为是定时炸弹.请使用同步结构,例如locks或mutexes.
好吧,只是为了完整性,这条线
while( tail > head );
Run Code Online (Sandbox Code Playgroud)
在方法中pop_back()应该是
while( tail >= head );
Run Code Online (Sandbox Code Playgroud)
除非你想要再弹出一个元素而不是你实际推入的元素(甚至在推入任何东西之前弹出一个元素).
很抱歉写一些基本归结为长期咆哮,但如果这只让一个人复制和粘贴那些淫秽的代码,那就值得.
更新:我想我也可以举一个例子,其中代码while(x>y);实际上是完全有道理的.实际上你过去经常在"好日子"里看到这样的代码.咳嗽 DOS.虽然没有在线程的上下文中使用.主要是作为一个后备,以防注册中断挂钩是不可能的(你的孩子可能会将其翻译为"无法注册事件处理程序").
startAsynchronousDeviceOperation(..);
Run Code Online (Sandbox Code Playgroud)
这可能是几乎任何事情,例如告诉硬盘通过DMA读取数据,或告诉声卡通过DMA记录,甚至可能调用不同处理器(如GPU)上的功能.通常通过类似的东西发起outb(2).
while(byteswritten==0); // or while (status!=DONE);
Run Code Online (Sandbox Code Playgroud)
如果与设备的唯一通信通道是共享内存,那么就这样吧.不希望现在看到类似于设备驱动程序和微控制器之外的代码.显然假设规范声明内存位置是写入的最后一个.
该volatile关键字旨在阻止某些优化.在这种情况下,如果没有关键字,编译器可以将while循环展开为具体的指令序列,这些指令显然会在现实中破坏,因为值可以在外部修改.
想象一下:
int i = 2;
while (i-- > 0) printf("%d", i);
Run Code Online (Sandbox Code Playgroud)
大多数编译器会查看这个并简单地生成两个调用printf- 添加volatile关键字将导致它生成CPU指令,调用计数器设置为2并在每次迭代后检查值.
例如,
volatile int i = 2;
this_function_runs_on_another_process_and_modifies_the_value(&i);
while(i-- > 0) printf("%d", i);
Run Code Online (Sandbox Code Playgroud)