C#和C++中的volatile关键字

volatile keyword in C# and C++

本文关键字:volatile 关键字 中的 C++      更新时间:2023-10-16

在C++中,我被教导对不同线程使用的变量(myVar)使用volatile关键字,即使在关键部分也是如此。但对于C#,我在MSDN上读到了这样一句奇怪的话:"volatile修饰符通常用于多个线程访问的字段,而不使用lock语句序列化访问。"这个短语的意思是,如果我被锁定,那么就不需要使用volatile关键字吗?如果是,那么还有一个问题:可能我必须锁定exect这个变量(myVar)?

Object a = new Object();
double i,k;
Thread1()
{
lock(a)
{
i++;// using variable i.
k++;// using variable k.
}
}

螺纹2也会这样做。i和k不易挥发是安全的吗?还是我必须这样做?:

lock(i)
{
i++;// using variable i.
}
lock(k)
{
k++;// using variable k.
}

在C++中,我被教导对不同线程使用的变量(myVar)使用volatile关键字,即使在关键部分下也是如此

谁教你这并不是在教你整个故事。C++中的Volatile不能保证读取或写入具有获取或释放语义!所有volatile的保证是编译器不会生成省略读取或无序读取和写入的代码只有Volatile不足以确保多线程中的正确语义,除非编译器对"Volatile"的含义做出一些额外的声明。

volatile修饰符通常用于多个线程访问的字段,而不使用lock语句序列化访问。"这个短语的意思是,如果我被锁定,那么就不需要使用volatile关键字吗?

正确。在C#中,volatile确实通过插入适当的半栅栏来引入获取和释放语义。由于锁引入了完整的围栏,因此在读取锁中的字段时不需要volatile。

可能是我必须锁定exect这个变量(myVar)?

所有这些代码都是完全错误的,无法回答这个问题。++在doubles上是危险的,使doubles不稳定在C#中甚至是不合法的,并且不能锁定值类型。

在标准C++中,volatile与线程无关,尽管显然微软的编译器赋予了它一些特殊的含义。对于计数器之类的东西,请使用std::atomic<int>;不需要单独的锁。

正确,在lock下的C#中,您不需要使用volatile,因为使用lock可以确保所有线程都看到最新的值。

我同意你的看法,这在MSDN文档中并不清楚:lock只提供对代码块的互斥访问,但除此之外,它还具有其他线程安全特性,例如确保每个线程都看到相同的值,这是lock固有的,因为它使用内存屏障。

你的第二个问题是不可能的——你必须在引用类型上使用lock——然而,假设你这样做了,在这两种情况下,如果所有其他对变量的读写都锁定在同一个实例上,那么你的操作都是"线程安全的",通常情况下,更细粒度的对象更好,这样你就不必让其他线程在想要更新其他东西时等待,而必须获取相同的锁,但您可能知道这些var总是一起访问的,在这种情况下,共享锁会更有效率。