Comments
The classic solution to this problem is to use mutual exclusion on the class that indicates that the object is being instantiated.
Code
1. using System; 2. using System.Collections.Generic; 3. using System.Threading; 4. 5. namespace DoFactory.GangOfFour.Singleton.RealWorld 6. { 7. ///8. /// MainApp startup class for Real-World 9. /// Singleton Design Pattern. 10. /// 11. class MainApp 12. { 13. ///14. /// Entry point into console application. 15. /// 16. static void Main() 17. { 18. LoadBalancer b1 = LoadBalancer.GetLoadBalancer(); 19. LoadBalancer b2 = LoadBalancer.GetLoadBalancer(); 20. LoadBalancer b3 = LoadBalancer.GetLoadBalancer(); 21. LoadBalancer b4 = LoadBalancer.GetLoadBalancer(); 22. 23. // Same instance? 24. if (b1 == b2 && b2 == b3 && b3 == b4) 25. { 26. Console.WriteLine("Same instance\n"); 27. } 28. 29. // Load balance 15 server requests 30. LoadBalancer balancer = LoadBalancer.GetLoadBalancer(); 31. for (int i = 0; i < 15; i++) 32. { 33. string server = balancer.Server; 34. Console.WriteLine("Dispatch Request to: " + server); 35. } 36. 37. // Wait for user 38. Console.ReadKey(); 39. } 40. } 41. 42. ///43. /// The 'Singleton' class 44. /// 45. class LoadBalancer 46. { 47. private static LoadBalancer _instance; 48. private List_servers = new List (); 49. private Random _random = new Random(); 50. 51. // Lock synchronization object 52. private static object syncLock = new object(); 53. 54. // Constructor (protected) 55. protected LoadBalancer() 56. { 57. // List of available servers 58. _servers.Add("ServerI"); 59. _servers.Add("ServerII"); 60. _servers.Add("ServerIII"); 61. _servers.Add("ServerIV"); 62. _servers.Add("ServerV"); 63. } 64. 65. public static LoadBalancer GetLoadBalancer() 66. { 67. // Support multithreaded applications through 68. // 'Double checked locking' pattern which (once 69. // the instance exists) avoids locking each 70. // time the method is invoked 71. if (_instance == null) 72. { 73. lock (syncLock) 74. { 75. if (_instance == null) 76. { 77. _instance = new LoadBalancer(); 78. } 79. } 80. } 81. 82. return _instance; 83. } 84. 85. // Simple, but effective random load balancer 86. public string Server 87. { 88. get 89. { 90. int r = _random.Next(_servers.Count); 91. return _servers[r].ToString(); 92. } 93. } 94. } 95. }