Locking a single bool variable when multithreading?
Solution 1
Yes, it is needed. .Net environment uses some optimizations, and sometimes if a memory location is accessed frequently, data is moved into CPU registers. So, in this case, if mbTestFinished is in a CPU register, then a thread reading it may get a wrong value. Thus using the volatile key ensures, all accesses to this variable is done at the memory location, not at the registers. On the otherhand, I have no idea of the frequency of this occurence. This may occur at a very low frequency.
Solution 2
In my opinion, no, the lock is superfluous here, for two reasons:
- Boolean variables cannot cause assignment tearing like
long
for example, hence locking is not necessary. - To solve the visibility problem
volatile
is enough. It's true that thelock
introduces an implicit fence, but since thelock
is not required for atomicity,volatile
is enough.
Solution 3
If mLock is ONLY for the variable mbTestFinished, then it's a bit of an overkill. Instead, you can use volatile or Interlocked, because both are User-Mode constructs for thread synchronization. lock (or Monitor) is a Hybrid Construct, in the sense that it is well optimized to avoid transiting from/to the Kernel-Mode whenever possible. The book "CLR via C#" has a in-depth discussion of these concepts.
Related videos on Youtube
Daniel Peñalba
Software Engineer at Unity Technologies, Valladolid, Spain. Currently developing gmaster, Plastic SCM and SemanticMerge. Areas: C# GUI development Winforms and WPF expert ASP .NET Core Multiplatform UI development with Mono (Linux and OSX, GTK# and MonoMac) Eclipse plugin, Java Automated testing, NUnit, Moq, PNUnit and TestComplete Email: dpenalba[AT]codicesoftware[DOT]com I play the guitar at Sharon Bates, the greatest Spanish rock band.
Updated on June 18, 2022Comments
-
Daniel Peñalba almost 2 years
Recently I have seen this code in a WebSite, and my question is the following:
private bool mbTestFinished = false; private bool IsFinished() { lock( mLock ) { return mbTestFinished; } } internal void SetFinished() { lock( mLock ) { mbTestFinished = true; } }
In a multithread environment, is really necessary to lock the access to the
mbTestFinished
?-
Marc Gravell about 12 yearsIt is the most provable mechanism for ensuring it isn't a CPU-cached read (which would not work well between threads) -
volatile
would work too, but for reasons that are too complex (this isn't the intent ofvolatile
, but rather: a side-effect) -
Roman Starkov about 12 years@MarcGravell I’ve always thought that was the intent of
volatile
; any chance you might drop a good link that explains what is?
-
-
Roman Starkov about 12 yearsThis is true assuming the code shown is the only thing using the lock. If there are other places where
mLock
is taken, the conversion tovolatile
could break things. -
Tudor about 12 years@romkyns: Yes, I'm assuming it's a self-contained scenario.