Your code is not thread safe because you use a double-control lock without making the field unstable. Unfortunately, VB.NET does not have a mutable modifier, so you cannot apply a normal fix. Just acquire a lock every time instead, or use static initialization to initialize _CompiledRegExes when the type is initialized.
See my one-page page for a general discussion of this issue with respect to single cells - I know this is not exactly a singleton, but it is Close. The page gives C # code, but it should be pretty easy to understand.
In addition, I usually recommend doing read-only lock variables. You really don't want to change the value :)
In outline:
- No, static properties are not thread safe automatically
- Yes, it's okay to block a static variable (but initialize it explicitly, just like you)
- Do not try to write lock code or with a low lock level if you really do not know what you are doing. I consider myself knowledgeable enough about threads, and I'm still not trying to use double check locking, etc.
- Type initialization is thread safe (with a few caveats, if you have complex initializers that end up referencing each other) to have a good initialization like this - then you really don't need a lock.
EDIT: You do not need to specify a singleton type. Just write a function to initialize the list and return it, then use this function in the initializer for the variable:
' This has to be declared *before* _CompiledRegExes ' ' as the initializer will execute in textual order ' ' Alternatively, just create the array inside BuildRegExes ' ' and don't have it as a field at all. Unless you need the array ' ' elsewhere, that would be a better idea. ' Private Shared ReadOnly Regexes() As String = {"test1.Regex", "test2.Regex"} Private Shared ReadOnly _CompiledRegExes As List(Of Regex) = BuildRegExes() Private Shared ReadOnly Property CompiledRegExes() As List(Of Regex) Get Return _CompiledRegExes End Get End Property Private Shared Function BuildRegExes() As List(Of Regex) Dim list = New List(Of Regex)(Regexes.Length - 1) For Each exp As String In Regexes _CompiledRegExes.Add(New Regex(exp, RegexOptions.Compiled Or RegexOptions.CultureInvariant Or RegexOptions.IgnoreCase)) Next Return list End Function
source share