Reputation: 31
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.
}
Upvotes: 3
Views: 851
Reputation: 659956
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.
Upvotes: 6
Reputation: 11426
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.
Upvotes: 0
Reputation: 76235
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.
Upvotes: 3