Maury Markowitz Maury Markowitz - 1 month ago 10x Question

Is it safe to call SyncLock and MemoryBarrier even if you're not in a separate thread?

A follow-up to this post. My goal is to have only one

at a time, so I have added a SyncLock:

Public Sub Calculate(Optional inBack As Boolean = True)
If Not inBack Then
InternalCalculate(-1, False)
If CalcThread IsNot Nothing Then
CalcThread.Abort() ' yes, I will replace this
CalcThread = Nothing ' XXX
End If
If CalcThread Is Nothing Then
CalcThread = New Threading.Thread(AddressOf InternalCalculate)
CalcThread.IsBackground = True
End If
End If
End Sub

Private Sub InternalCalculate(Optional Line As Integer = -1, Optional isBack As Boolean = True)
Dim Lock As New Object
SyncLock Lock
Threading.Thread.MemoryBarrier() ' do this BEFORE a write, right?
isRunning = true
'do the expensive stuff
End SyncLock
End Sub

Note the
. If this is false the code should just run in main. This is commonly used when recalculating a single
. So my question is about the safety of these two lines:

SyncLock Lock

It is not clear to me in the documentation what happens if I call these in code running in main. I have added the code, and it seems to run OK, but I want to make sure I'm not opening myself to another gotcha, like Abort. Are these OK for both threaded and non-threaded uses?


Yes it's safe to use them in single threaded code.

There are issues however with your InternalCalculate which will allow it to execute code concurrently. Every call to InternalCalculate creates a new Lock object. Synclock will only block threads if these use the same object so make Lock a readonly member variable.

If you then execute multiple threads then the second, third, fourth etc will wait until the first one to obtain the lock exits the sync lock block. Then the others will go. So if this is code that should only be executed once you should check out the double check lock pattern.

Instead of adding MemoryBarriers for the reading / writing of volatile data, I'd suggest you use System.Threading.Thread.VolatileRead and System.Threading.Thread.VolatileWrite. Then you don't need to remember which order to do your reads / writes in.