简体   繁体   English

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

[英]volatile keyword in C# and C++

In C++ I'm taught to use volatile keyword for variable (myVar) that is used from different threads even under critical section. 在C ++中,我教会使用volatile关键字变量(myVar),即使在关键部分也可以使用不同的线程。 But for C# I read in MSDN this strange phrase: "The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access." 但对于C#,我在MSDN中读到了这个奇怪的短语:“volatile修饰符通常用于多个线程访问的字段,而不使用lock语句来序列化访问。” Does this phrase mean that if I'm under lock then do not need to use volatile keyword? 这句话是否意味着如果我处于锁定状态,那么不需要使用volatile关键字? If yes, then one more question: may be I must do lock on exect this variable (myVar)? 如果是,那么还有一个问题:可能是我必须锁定exect这个变量(myVar)?

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

Thread2 do the same. Thread2也是如此。 Is it safe that i and k not volatile, or I must do like that?: 我和k没有波动是否安全,或者我必须这样做?:

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

In C++ I'm taught to use volatile keyword for variable (myVar) that is used from different threads even under critical section 在C ++中,我教会使用volatile关键字变量(myVar),即使在关键部分也可以使用不同的线程

Whomever taught you this is not teaching you the whole story. 谁教你,这不是教你整个故事。 Volatile in C++ makes no guarantees that reads or writes have acquire or release semantics! C ++中的Volatile不能保证读取或写入具有获取或释放语义! All volatile guarantees is that the compiler will not generate code that elides reads or does reads and writes out of order. 所有易失性保证是编译器不会生成elides读取或无序读写的代码。 Volatile alone is not enough to ensure correct semantics in multithreading unless your compiler makes some additional claim about what "volatile" means to it. 单独使用Volatile不足以确保多线程中的正确语义,除非您的编译器对“volatile”对其意味着什么做出了额外的声明。

The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access." Does this phrase mean that if I'm under lock then do not need to use volatile keyword? volatile修饰符通常用于多个线程访问的字段,而不使用lock语句来序列化访问。“这句话是否意味着如果我处于锁定状态,那么不需要使用volatile关键字?

Correct. 正确。 In C#, volatile does introduce acquire and release semantics by inserting the appropriate half fence. 在C#,易失性确实引入获取和通过将合适的半围栏释放语义。 Since a lock introduces a full fence, volatile is unnecessary when reading a field in a lock. 由于锁引入了完整的栅栏,因此在读取锁中的字段时不需要volatile。

may be I must do lock on exect this variable (myVar)? 可能我必须锁定exect这个变量(myVar)?

All this code is so completely broken and wrong that it is impossible to answer the question. 所有这些代码都是如此完全破碎和错误,以至于无法回答这个问题。 ++ is dangerous on doubles, making doubles volatile is not even legal in C#, and you can't lock on value types. ++对双打是危险的,使得双精度易失性在C#中甚至不合法,并且你无法锁定值类型。

In standard C++ volatile has nothing to do with threads, although apparently Microsoft's compiler gives it some special meaning. 在标准的C ++中, volatile与线程无关,虽然显然微软的编译器给它一些特殊的含义。 For things like counters, use std::atomic<int> ; 对于像计数器这样的东西,使用std::atomic<int> ; no need for separate locks. 不需要单独的锁。

Correct, in C# under lock you do not need to use volatile because using lock guarantees all threads see the most up-to-date value. 正确,在C#under lock下你不需要使用volatile因为使用lock保证所有线程都能看到最新的值。

I agree with you, this is not clear from the MSDN documentation: lock is made out to only provide mutual exclusive access to a block of code, but in addition it also has other thread-safety featues such as ensuring every thread sees the same value, this in inherent in lock because it uses memory barriers. 我同意你的看法,这在MSDN文档中并不清楚: lock只是为了提供对代码块的互斥访问,但此外它还具有其他线程安全特性,例如确保每个线程都看到相同的值这是固有的lock因为它使用了内存屏障。

Your second question is not possible - you have to lock on a reference type - supposing you did however, in both cases you operation is "thread-safe" provided all other reads and writes to the variables lock on the same instance, usually a more granule object is better so you do not have to make other threads wait when they want to update something else and have to acquire the same lock, but you may know these vars are always accessed together in which case a shared lock would be more efficient. 你的第二个问题是不可能的 - 你必须lock一个引用类型 - 假设你这样做了,但是在这两种情况下你的操作都是“线程安全的”,只要对变量的所有其他读写操作锁定在同一个实例上,通常更多granule对象更好,所以当他们想要更新其他东西并且必须获得相同的锁时,你不必让其他线程等待,但你可能知道这些变量总是一起访问,在这种情况下共享锁会更有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM