简体   繁体   中英

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. 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." Does this phrase mean that if I'm under lock then do not need to use volatile keyword? If yes, then one more question: may be I must do lock on exect this variable (myVar)?

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

Thread2 do the same. Is it safe that i and k not volatile, or I must do like that?:

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

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! All volatile guarantees is that the compiler will not generate code that elides reads or does reads and writes out of order. Volatile alone is not enough to ensure correct semantics in multithreading unless your compiler makes some additional claim about what "volatile" means to it.

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?

Correct. In C#, volatile does introduce acquire and release semantics by inserting the appropriate half fence. Since a lock introduces a full fence, volatile is unnecessary when reading a field in a lock.

may be I must do lock on exect this variable (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.

In standard C++ volatile has nothing to do with threads, although apparently Microsoft's compiler gives it some special meaning. For things like counters, use 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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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