Is it necessary to开发者_Go百科 acquire a lock on a variable before reading it from multiple threads?
The short answer is: it depends.
The long answer is:
If it is not a shared value, i.e, only one thread can see it (or use it), you don't need any synchronization.
If it is an immutable value, i.e., you set it only once and then only ever read, it is safe to do so without synchronization (as long as you don't start reading before the first write completes).
If it is a "primitive" type of at most 32-bits (e.g.
byte
,short
,int
) you can get stale (old) data when reading. If that doesn't bother you, you're set. If stale data is undesirable, making the variablevolatile
can fix this problem without additional synchronization for reads. But if you have racing writers, you will need to follow the same advice as forlong
s below.If it is a "primitive" type longer than 32-bits (e.g.
long
,decimal
,double
) you need synchronization, otherwise you could read "half" of one value, "half" of another, and get crazy results. For this the recommended approach is to use the methods in theInterlocked
class, for both reads and writes..If it is a reference type, you will need synchronization to avoid seeing an invalid state (Jeff Lamb's picture example is a good one). The
lock
statement might be enough for that. Again, you need to lock for both reads and writes.
There are some other points to consider (how long to lock, for example), but I think these are enough to answer your question.
It depends on the type of variable and your platform. For example, reading Int64s is not guaranteed to be atomic on 32 bit machines. Hence, Interlocked.Read
.
If the loading of the value is done in 1 assembly instruction, it's not necessary to get a lock. You don't care if the value changed 10 minutes ago or 1 microsecond ago. You just want the value now.
However, if you're loading a HUGE array or picture or something, it'd probably be a good idea to lock it out. In theory, you can get preempted while loading the data and have half of the first item and half of the second item.
If it's a simple variable, though, like a bool or int, it's not necessary.
In adition to the answers below you can also do a read lock using the ReadWriterLockSlim.
That would allow you to do only a read lock when reading and a write lock when modifying your variable. Multiple threads can have a read lock at the same time but as soon as a thread requests a write lock all new request are blocked until it is complete.
This sort of locking would be usefull if you are doing alot of reads and not many writes.
As with most multithreading issues, research it enough to understand if it really fits your problem the ReadWriterLock would not be suitable for every locking situation.
It depends on whether or not is it a local or shared variable, and whether something else may write to it in the meantime, and what you're going to do after reading it.
If you make a decision based on the variable, consider that the next line of code may then be based on data which is now stale.
Answer is it depends. If the value of the variable does not change when the threads are accessing the variable. otherwise, its needed.
Also, You can use Interlocked.XXX series for maintaining atomicity in reading\writing the variable .
Reading does not require a lock; as long as you don't care about the 'correctness' of the read. It is only dangerous if you attempt to write without a lock.
If it is a constant, no.
If it is an updatable value, yes, if you need consistency.
For updatable values where the exact value must be managed, then yes, you should use a lock or other synchronization method for reads and writes; and perhaps block during the entire scope where the value is used.
It is 100% necessary unless you are 100% sure that the variable's value won't change while the reader threads are running.
Necessary? No.
...but if it's possible that another thread could try to write to it during the read (like a collection, etc.) then it might be a good idea.
As long as it doesn't change during others threads execution you don't need to lock it. If change, you should use it.
If the variable is never written to by someone (at least at the time it is accessible), you don't need to lock it, because there are no possibilities for missed updates. The same goes if you don't care about missed updates (meaning it is not a problem if you get an older value). Otherwise you should use some sort of synchronization
精彩评论