The Singleton pattern ensures that a class has only one instance and provides a global point of access to it. In VB.NET, a private constructor and a static property are commonly used to hold the single instance:
Public Class Singleton Private Shared _instance As Singleton Private Sub New() ' Private constructor End Sub Public Shared ReadOnly Property Instance() As Singleton Get If _instance Is Nothing Then _instance = New Singleton() End If Return _instance End Get End Property End Class
Thread Safety:
In a multithreaded environment, it is possible to create two instances when accessed simultaneously. Solution: use locking or the Lazy(Of T) construct:
' Lazy thread-safe implementation Public Class Singleton Private Shared ReadOnly _instance As New Lazy(Of Singleton)(Function() New Singleton()) Private Sub New() End Sub Public Shared ReadOnly Property Instance() As Singleton Get Return _instance.Value End Get End Property End Class
Difference:
What is dangerous about such a code for implementing Singleton?
Public Shared ReadOnly Property Instance() As Singleton Get If _instance Is Nothing Then _instance = New Singleton() End If Return _instance End Get End Property
Answer: In a multithreaded environment, there may be a situation where two threads simultaneously see that _instance is Nothing and both create an object. Therefore, this approach is not completely thread-safe. It is recommended to use Lazy(Of T) or SyncLock for locking.
Story
ERP system: Singleton logger sometimes created twice when started from services, losing logs. The reason was the lack of synchronization in the property, even though the application was multithreaded.
Story
Windows Forms application: In the project, database work was extracted into a Singleton, but lazy initialization was not implemented. Upon application startup, a heavy connection occurred, slowing down UI loading for everyone.
Story
Plugin for a journalistic platform: Tried to use a static variable in a module for Singleton, which was not protected from multithreaded access; as a result, several instances of the email distribution handler appeared during peak load, causing duplicate emails.