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. }