Is this code correct or is there any possibility of some random threading deadlocks etc?
Is it a good idea to use static properties and locking together? Or is static property thread-safe anyway?
Private Shared _CompiledRegExes As List(Of Regex) Private Shared Regexes() As String = {'test1.Regex', 'test2.Regex'} Private Shared RegExSetupLock As New Object Private Shared ReadOnly Property CompiledRegExes() As List(Of Regex) Get If _CompiledRegExes Is Nothing Then SyncLock RegExSetupLock If _CompiledRegExes Is Nothing Then _CompiledRegExes = New List(Of Regex)(Regexes.Length - 1) For Each exp As String In Parser.Regexes _CompiledRegExes.Add(New Regex(exp, RegexOptions.Compiled Or RegexOptions.CultureInvariant Or RegexOptions.IgnoreCase)) Next End If End SyncLock End If Return _CompiledRegExes End Get End Property
If it’s not obvious code is compiling regexes and storing in a List(Of Regex) so they can run faster. And it’s shared so every instance of class can get benefit out of it.
Your code isn’t thread-safe because you’re using double-checked locking without making the field volatile. Unfortunately VB.NET doesn’t have a volatile modifier, so you can’t apply the normal fix. Just acquire the lock every time instead, or use static initialization to initialize _CompiledRegExes when the type is initialized.
See my singleton page for a general discussion of this with regards to singletons – I know this isn’t quite a singleton, but it’s close. The page gives C# code, but it should be fairly easy to understand.
Additionally, I generally recommend making lock variables read-only. You really don’t want to be changing the value 🙂
In general terms:
EDIT: You don’t need to make the type a singleton. Just write function to initialize the list and return it, then use that function in the initializer for the variable: