我正在阅读关于volatile关键字的这个问题的答案:
这个人说:
防止重新排序的解决方案是使用内存屏障,该内存屏障向编译器和CPU指示在该点上不能重新排序内存访问.在易失性变量访问周围放置这些障碍可确保即使非易失性访问也不会在易失性访问中重新排序,从而允许我们编写线程安全的代码.
但是,内存障碍还可以确保在达到屏障时执行所有挂起的读/写操作,因此它有效地为我们提供了我们自己需要的所有内容,从而使得volatile不必要.我们可以完全删除volatile限定符.
这个"内存障碍"在C++中是如何实现的?
编辑:
有人可以给出一个简单的代码示例吗?
我最近在阅读Crack Code Interview这本书,但在第257页有一段让我很困惑:
线程是进程的特定执行路径; 当一个线程修改进程资源时,对兄弟线程立即可以看到更改.
IIRC,如果一个线程对变量进行了更改,则更改将首先保存在CPU缓存中(例如,L1缓存),并且除非将变量声明为volatile,否则不保证与其他线程同步.
我对吗?
我读过在某些情况下(全局变量,或while(变量)等),如果未定义变量volatile,可能会导致问题.
如果我将所有变量定义为volatile,会导致问题吗?
我正在写一个C++应用程序.
我有一个多个线程正在写入的类变量.
在C++中,任何可以在没有编译器"意识到"它被更改的情况下进行修改的东西都需要标记为volatile吗?因此,如果我的代码是多线程的,并且一个线程可以写入var而另一个线程从中读取,我是否需要标记var volaltile?
[我没有竞争条件,因为我依赖于对原子的写入]
谢谢!
在boost::shared_ptr析构函数中,这样做:
if(--*pn == 0)
{
boost::checked_delete(px);
delete pn;
}
Run Code Online (Sandbox Code Playgroud)
其中pn是一个指向引用计数器的指针,该指针的类型定义为
shared_ptr::count_type -> detail::atomic_count -> long
Run Code Online (Sandbox Code Playgroud)
我本来期望的long是volatile long在给定螺纹使用和非原子0检查和-删除shared_ptr上述析构函数.为什么不变化?
编辑:
事实证明,我查看了未指定多线程使用时使用的标头(atomic_count.hpp).在atomic_count_win32.hpp中,为多线程用法正确实现了减量.
全局指针在线程之间是否存在范围?
例如,假设我有两个文件,file1.c和file2.c:
file1.c中:
uint64_t *g_ptr = NULL;
modify_ptr(&g_ptr) {
//code to modify g_ptr to point to a valid address
}
read_from_addr() {
//code which uses g_ptr to read values from the memory it's pointing to
}
Run Code Online (Sandbox Code Playgroud)
file2.c中:
function2A() {
read_from_addr();
}
Run Code Online (Sandbox Code Playgroud)
所以我有threadA,它运行在file1.c中并执行modify_ptr(&g_ptr)和read_from_addr().然后threadB运行,它通过执行function2A()的file2.c运行.
我的问题是:threadB是否看到g_ptr被修改了?或者它仍然看到它指向NULL?
如果不是这样,那么指针是全局的意味着什么?如何确保在不同线程之间可以访问此指针?
如果我需要澄清任何事情,请告诉我.谢谢
我正在阅读有关错误共享和缓存乒乓的信息,当不同内核上有多个线程尝试使用相同的缓存行但数据不同时(例如数组中彼此相邻的两个 int 值)。在这种情况下,缓存线需要在核心之间来回移动。我感到困惑的是,我认为每个核心都有自己的 L1 缓存,那么为什么它需要与其他核心共享该缓存行?难道它不只是保留自己的副本并更新它吗?另外,如果 cpu 被迫使核心之间的所有缓存保持一致,那么像 c++ 中这样的关键字有什么意义volatile(除了可能阻止编译器将值存储在寄存器中)?
我正在编写一个音频应用程序,它有多个线程产生声音,一个线程混合声音并将它们发送到声卡.我已经尝试了几种同步线程的方法,包括信号和线程安全队列在内的"正确"方式,但它们都太慢了.所以现在我为每个生产者使用bool来指示它的队列是否已满.它似乎工作得很好(32个线程的5ms延迟),但这样做是否安全?
class PlayThreadParameters
{
public Queue<Samples> queue;
public bool isOutputQueueFull;
}
Run Code Online (Sandbox Code Playgroud)
制片人看起来像这样:
public void PolyPlayThread(object o)
{
var playThreadParameters = (PlayThreadParameters)o;
while (isPlaying)
{
while (playThreadParameters.isOutputQueueFull)
{
if (!isPlaying)
return;
Thread.Sleep(1);
}
... //fill output queue
playThreadParameters.isOutputQueueFull = true;
}
}
Run Code Online (Sandbox Code Playgroud)
消费者看起来像这样(由Naudio的一个单独的线程调用):
public override int Read(byte[] array, int offset, int count)
{
for (int v = 0; v < playThreadParameters.Length; v++)
while (!playThreadParameters[v].isOutputQueueFull)
{
if (!isPlaying)
return 0;
Thread.Sleep(1);
}
... //mix the samples from the outputqueues
for (int v …Run Code Online (Sandbox Code Playgroud) 方案如下:线程A继续执行,直到它从线程B收到一个停止从控制台读取输入的停止信号.
实现这个的最佳方法是什么?例如,我想我可以将它实现为一个全局变量,线程A每隔一段时间就会检查一次,而线程B可以改为发出"停止"信号,
但我不知道这是不是正确的方法.
即使它是正确的,我应该使用"Volatile"还是"Atomic <>"?特别是线程A只读取变量的值,而线程B只写入变量.
如果在线程A读取它之后立即从线程B修改变量并不重要(不会引起问题"线程A退出时间有些放松(在信号之后容忍)")?
是否还有另一种方法让线程B启动线程A并在需要时停止它?
注意!
我显然没有向这里的每个人清楚地表明我的观点,这令人非常沮丧.我的目标是打消那种
volatile实际上是无操作的神话,它什么都不做.我并没有试图说它应该被使用,它是必不可少的,它不是多余的,等等.我已经表明
volatile它仍然可以做一件事.我承认在某些情况下它是多余的,并且多线程示例是一个糟糕的选择.我也没有试图隐瞒我的答案的初始修订包含错误这一事实.但这个Q&A甚至没有达到其预期目的.为此,我认为是时候把它扔掉了.
感谢Kerrek和TC的见解.我只是不认为他们的回答符合我想问的问题.我很确定这是我的错,因为它很糟糕.
所以我放弃了!并将其作为问题的副本而不是它的意图,但它被解释为.
干杯! (&hth.)
我正在写一个线程中的变量并在另一个线程中读取它.我被告知这对我volatile来说完全无用,除非我正在使用硬件,否则我不需要在这个时代使用它.
int x = 0;
void thread1()
{
while (true) {
sleep(1);
if (x > 0)
break;
}
}
void thread2()
{
while (true) {
sleep(1);
x++;
}
}
Run Code Online (Sandbox Code Playgroud)
volatile在这种情况下,我可以获得任何收益吗?
如果x不是一个简单int的类而是一个类类型怎么样?