My question is then, since I only access these objects from the ObjectRepository, do I gain anything by creating the base services as extendable (inheritable) singletons or should I just access them as shared members directly? Now what gets a little trickier is that the application is a server-side application and objects are activated as single-call objects, so depending on the load on the server the application service objects may not be around and may need to be created on the next round if the aspnet worker process is recycled, right? Anyways, I've got the system scaling really well not using the singleton pattern and just accessing the services as shared members of the ObjectRepository, but I'm just curious if using the singleton pattern in this situation will be more performant. Of course, since I need to have the services inheritable, if I go with the singletn pattern I will have to maintain the pattern on all the sub-classes so code maintenance has a weigh-in factor here as well.
So let me show you what I mean. Should I do this (what I'm doing now):
Public Class MyBaseService1 Public Sub New() Initialize() End Sub Private Sub Initialize() 'do initialization stuff End Sub Public Sub TemplateMethod() HookMethod1() HookMethod2() End Sub Protected Overridable Sub HookMethod1() 'do default stuff End Sub Protected Overridable Sub HookMethod2() 'do more default stuff End Sub End Class Public Class MyExtendedService1 Inherits MyBaseService1 Public Sub New() MyBase.New() End Sub Protected Overrides Sub HookMethod1() 'do different stuff End Sub Protected Overrides Sub HookMethod2() 'do more different stuff End Sub End Class Public Class ObjectRepository1 Private Shared m_service1 As MyExtendedService1 Private Shared _lock As New Object 'Use lazy initialization because this ' class is rarely used and expensive to create. Public Shared ReadOnly Property Service1() As MyExtendedService1 Get If m_service1 Is Nothing Then SyncLock (_lock) If m_service1 Is Nothing Then m_service1 = New MyExtendedService1 End If End SyncLock End If Return m_service1 End Get End Property End ClasOr would it be better to implement this pattern?
Public Class MyBaseService Protected Shared _Instance As MyBaseService Protected Shared _Lock As New Object Protected Sub New() Initialize() End Sub Public Shared Function GetInstance() As MyBaseService If _Instance Is Nothing Then SyncLock (_Lock) If _Instance Is Nothing Then _Instance = New MyBaseService End If End SyncLock End If Return _Instance End Function Private Sub Initialize() 'do initialization stuff End Sub Public Sub TemplateMethod() HookMethod1() HookMethod2() End Sub Protected Overridable Sub HookMethod1() 'do default stuff End Sub Protected Overridable Sub HookMethod2() 'do more default stuff End Sub End Class Public Class MyExtendedService Inherits MyBaseService Public Shared Shadows Function GetInstance() As MyExtendedService If _Instance Is Nothing Then SyncLock (_Lock) If _Instance Is Nothing Then _Instance = New MyExtendedService End If End SyncLock End If Return DirectCast(_Instance, MyExtendedService) End Function Protected Overrides Sub HookMethod1() 'do different stuff End Sub Protected Overrides Sub HookMethod2() 'do more different stuff End Sub End Class Public Class ObjectRepository Private Shared m_service1 As MyExtendedService 'Use lazy initialization because this ' class is rarely used and expensive to create. Public Shared ReadOnly Property Service1() As MyExtendedService Get If m_service1 Is Nothing Then m_service1 = MyExtendedService.GetInstance() End If Return m_service1 End Get End Property End ClassI mean, I really don't see the advantage of this pattern for my situation but maybe I'm missing something? Thanks in advance!
6 comments:
The next article might be interesting to you :
Implementing the Singleton Pattern in C#
I based one of my singleton implementation on it, you can find the vb.net code over here (please do not try to read the Dutch part) : http://www.heefthetover.net/sdotone/?p=14
Thanks for the tips. The article you point to is quite interesting and has raised even more questions for me :-). I was under the impression that the double-checked locking pattern did work in .NET. (See this MSDN article) If not, what is the proper way to implement a thread-safe lazy initialization pattern in .NET? Can someone point me to more information on proof that the double checked locking pattern is broken in .NET?
Check out the post I made why singletons are evil. Just more to think about. http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx
I think I'm going to leave my code as is because the ObjectRepository maintains the single shared instances of the application services and those service classes can be inherited easier if they do not implement the singleton pattern (Scott, thanks for the convincing). However, since my ObjectRepository only calls the service factory to create the shared service when it is requested (lazy initialization), I am concerned how to implement this pattern in a thread-safe way. Right now I am using the double-checked locking pattern. Is this is not a good idea? If not, what's the solution?
Oh cuncurrency how I hate thee. Your best bet is the double checked locking, but know that you can still get a race condition so your variable needs to be volatile. Read this (http://blogs.msdn.com/brada/archive/2004/05/12/130935.aspx) to get the answer of why. I don't know VB.NET (I am a C++ / C# guy), but I am sure they have the same idea of a volatile in VB.NET.
scott
Oh my god, Magnum! Ok so it sounds like I should just do the Lock every time the read is attempted to be on the safe side and forget this double-check locking patten. Memory barriers are giving me a headache. But the thing is these shared members are actually in memory until the aspnet worker process is recycled so there is only a very very very slim chance that I'll ever see a race condition in this situation. But better safe than sorry, I admit. I'm going to do some performace tests and I'll post my final descision. Thanks for all the help.
Post a Comment