Implementing the Singleton Pattern in Visual Basic.Net

Object creation can be expensive in terms of processing time and memory utilization. While there are cases where multiple object instances are inevitable to getting things done, there are certainly cases where only a single instance of object is sufficient. For example, if your program is only going to access a single database instance, it suffice to dedicate a single object that manages database connection(s) to your database server. Other examples are objects used for logging messages, objects used for loading/saving configuration details, objects used for managing threads and objects used for managing access to shared hardware devices such as the printer.

How to make a class a Singleton?

  • Declare every constructor in the class to prevent instantiation from outside of the class.
  • Allocate memory to hold the single object instance, making it accessible only to fellow class members.
  • Expose at least one class member to retrieve the single object instance.

One sample implementation

Public Class Singleton

    ' Allocate memory space to hold the 
    ' single object instance
    Private Shared objSingleton As Singleton

    ' Make the only constructor private 
    ' to prevent initialization outside of 
    ' the class.
    Private Sub New()
        ' Heavy configuration works
    End Sub

    ' Expose getInstance() for the retrieval 
    ' of the single object instance.
    Public Shared Function getInstance() As Singleton

        ' Initialize singleton through lazy 
        ' initialization to prevent unused 
        ' singleton from taking up program 
        ' memory
        If (objSingleton Is Nothing) Then
            objSingleton = New Singleton()
        End If
        Return objSingleton

    End Function

End Class

The above sample will work as intended in single-threaded programs. However, in programs where the getInstance() method is accessed by multiple threads, more than one instances may be created and held by different threads. For instance, suppose Thread A and Thread B are accessing the getInstance() method at the same time. Thread A gets to run and is preempted right after it had checked that objSingleton is not yet initialized. Thread B runs and also checked that objSingleton is not yet initialized. When Thread A and Thread B complete the call to the getInstance() method, two instances of Singleton will be held by Thread A and Thread B concurrently.

Another implementation for multi-threaded programs

Imports System.Threading
Public Class Singleton

    ' For SyncLock to mark a critical section
    Private Shared classLocker As New Object()

    ' Allocate memory space to hold the 
    ' single object instance
    Private Shared objSingleton As Singleton

    ' Make the only constructor private 
    ' to prevent initialization outside of 
    ' the class.
    Private Sub New()
        ' Heavy configuration works
    End Sub

    ' Expose getInstance() for the retrieval 
    ' of the single object instance.
    Public Shared Function getInstance() As Singleton

        ' Initialize singleton through lazy 
        ' initialization to prevent unused 
        ' singleton from taking up program 
        ' memory
        If (objSingleton Is Nothing) Then
            ' Mark a critical section where 
            ' threads take turns to execute
            SyncLock (classLocker)
                If (objSingleton Is Nothing) Then
                    objSingleton = New Singleton()
                End If
            End SyncLock
        End If
        Return objSingleton

    End Function

End Class

The additional classLocker object is for the SyncLock construct to mark a critical section where Threads take turns to execute the coding. As SyncLock is expensive, we don't want every attempt to retrieve the singleton object to go through SyncLock, which is why we mark the critical section only when the singleton instance is not yet initialized. The same check inside the SyncLock block is to make sure that ultimately, only one thread will initialize the singleton object. For instance, in the Thread A and Thread B scenario mentioned earlier, both threads will queue up to execute the SyncLock block. Without the second check, both threads will initialize the singleton object when they get their turn to execute the critical section.

Advertisements

About Clivant

Clivant a.k.a Chai Heng enjoys composing software and building systems to serve people. He owns techcoil.com and hopes that whatever he had written and built so far had benefited people.

2 Comments

  • November 12, 2013 at 5:38 pm

    Thanks for this post. Just wanted to point out that your private constructors should not be Shared – you might want to fix that.

    • Clivant
      November 13, 2013 at 10:55 am

      Hi Daniel,

      Thanks for dropping by with your suggestion. I had updated the codes with your suggestion.

Advertisements
Advertisements