Why do we need a lock to implement the readonly int property?

I'm new to streaming, and I went through an example of implementing a custom pool thread on a blog. I insert only the necessary parts of the code:

Public Class ThreadPool Private CountLock As New Object Private _Count As Integer Public ReadOnly Property ThreadCount() As Integer Get SyncLock CountLock Return _Count End SyncLock End Get End Property Public Sub Open() Interlocked.Increment(_Count) End Sub Public Sub Close() Interlocked.Decrement(_Count) .... End Sub EndClass 

My question is, why do I need a lock to implement the readonly ThreadCount property?

+2
multithreading locking
source share
4 answers

A lock will force a memory barrier so that an outdated value from the CPU cache will not be read if the last value written was written by another CPU. The same can be done with Thread.VolatileRead() without blocking.

+1
source share

This code should use Interlocked.CompareExchange to access the value in the getter. Set param3 (comparand) to what you know you cannot see in a variable, for example Int32.MinValue , and then the function simply returns the current value of _count .

If Interlocked operations are used for all accesses to a variable, blocking is redundant, since all access through methods of the Interlocked class is atomic.

+2
source share

I have no idea why the author decided to use locking in one part of the class, while using locking technologies in other parts. However, I can assume that the author did this to create an explicit memory barrier when reading Interger . VB does not contain the C # volatile keyword equivalent, so it leaves only 4 other common methods for safe reading. I listed them in the order that I would choose for this particular scenario.

  • Interlocked.CompareExchange
  • Thread.VolatileRead
  • Thread.MemoryBarrier
  • Synclock

A memory lock is required to prevent the VB or JIT compiler. The most likely optimization in the absence of a memory barrier is to raise reads outside the loop. Consider this realistic use of the ThreadCount property.

 Sub LoggingThread() Do While True Trace.WriteLine(ThreadPool.ThreadCount) Loop End Sub 

In this example, the CLR will most likely have a ThreadCount built in, and then potentially " _Count up" to read _Count and _Count it in the CPU register before the start of the loop. The effect will be that the same value will always be displayed. one

1 In fact, the call to Trace.WriteLine creates a memory barrier that can lead to code being accidentally safe. The example was intended as a simple illustration of what might happen.

+2
source share

This makes no sense, as there is no lock in which you change the property. Perhaps the code had not used lock operations before and used SyncLock even in Open / Close? In this case, SyncLock would really need read access.

+1
source share

All Articles