1

I've got a class I want to use as a singleton by creating a static instance of it. Naturally I also want it to be thread safe.

Assume I am not sharing any private data. But if I am not mistaken, there still remains the problem that when calling a method of a static object instance, variables within methods are shared across threads, and would have unpredictable results.

However, when calling a real static method, a new stack frame is created, so it is thread safe (unto itself) anyway. Again, if I am not mistaken.

Would this pattern for a singleton be thread safe?

class Singleton
{
    public object SomeMethod(object arg) {
        return Singleton.SomeMethodImpl(arg);

    }
    private static object SomeMethodImpl(object arg) {
        // is in unique stack frame?
        object Result;
        ...
        return Result;
    }
}

In case you are wondering why I don't just create a static class in the first place - I need to have a singleton that is based on an interface, and has different implementations, as part of a strategy pattern. This doesn't work for static classes.

2
  • I would take a look at: dofactory.com/Patterns/PatternSingleton.aspx if you want a good example on how to create a singleton. Commented Jul 29, 2011 at 22:16
  • Just skimmed it. Good info - bookmarked. For my purposes now, I don't think I need to worry about locking since I'm not accessing any shared data within the class. Commented Jul 29, 2011 at 22:24

3 Answers 3

5

As long as your method isn't getting state from an instance method or global scope variable your method is reentrant and thread safe. It doesn't necessarily have to be static. So something like:

int AddTwo(int a, int b)
{
  return a + b;
}

That's perfectly thread safe and can be called as much as you like. Even defining variables inside of the method is fine as long as they are instance variables that are shared between methods.

A method such as:

string ReverseString(string s)
{
    char[] charArray = s.ToCharArray();
    Array.Reverse( charArray );
    return new string( charArray );
}

The method above is also reentrant and thread safe.

As soon as you start adding variables whether they are static or instance that come from a different scope you start having problems with thread safety.

class BadExample
{
    private int counter;

    private void IncrementCounter()
    {
        ++counter;
    }
}

In the above example the IncrementCounter() method is not thread safe.

Sign up to request clarification or add additional context in comments.

6 Comments

But if I define any local variables in a non-staic method it becomes un-thread-safe right? This is the problem I'm tryint to solve - I have to do stuff like pull things from a cache which require private temporary storage.
its not local variables that is the problem. its where the contents come from. In the example above, all of the "state" comes from arguments to the method. in your case, it depends on if your cache is thread safe. how is it written to? how is it read from?
The cache is fine, it's either a ConcurrentDictionary or HttpContext.Cache. But I was under the impression that defining a local variable in a non-static method of a statically-instantiated class would get you in trouble b/c two threads could call the method at the same time and share the same instance of that local variable.
Regarding your edit: so, basically, if I define no fields in a class (e.g. use no data except from external, thread-safe sources, or that is provided to the method as arguments), I can create a static instance of it and it will be thread safe? My initial premise is wrong -- calling a non-static member of a static instance of a class will still create a new stack frame for its private variables?
Everything created within the scope of that function is in that function's call stack. So unless you are getting your variables from elsewhere, no problems.
|
0

If I understand what you mean, then you're correct.

object Result;   // this is on its unique stack frame and is safe so far
Result = new ... // creating something on the heap that Result points to
                 // still safe because it's the only reference to it

Even if multiple threads call this they will create different new variables on the heap and assign them to Result on different stacks.

The only danger you'd be in is if you had private fields.

Variables within a method are temporary and only visible to that method call. Later or concurrent method calls recreate those variables separately.

Your only concern is static or instance fields. Those would need to be synchronized.

Comments

0

The code you have above is thread safe and for the reasons you've specified. The problem I see is you are not implementing a singleton.

Is your main worry about thread safety? If so, thread safety usually applies to object instance being share between threads. That means as long as you don't share a normal object across threads or create static data at the class level you should be ok.

I am adding an example of using singleton with interfaces, with and without a factory. Note: I didn't run this code.

public interface ISomething
{
    void Method();
}

public class Class1 : ISomething
{
    public void Method()
    {
        throw new NotImplementedException();
    }
}

public class Class2 : ISomething
{
    public void Method()
    {
        throw new NotImplementedException();
    }
}

public class Singleton
{
    private static ISomething privateObject;

    public static ISomething Instance()
    {
        lock (privateObject)
        {
            if (privateObject == null)
            {

                privateObject = new Class1();
            }
        }

        return privateObject;
    }
}

public class SingletonUsingFactory
{
    private static ISomething privateObject;

    public static ISomething Instance(int param)
    {
        lock (privateObject)
        {
            if (privateObject == null)
            {
                privateObject = FactoryClass.CreationObject(param);
            }
        }

        return privateObject;
    }
}

public static class FactoryClass
{
    public static ISomething CreationObject(int whatToCreate)
    {
        ISomething createdObject;

        switch (whatToCreate)
        {
            case 0:
                createdObject = new Class1();
                break;
            case 1:
                createdObject = new Class2();
                break;
            default:
                throw new Exception();
        }

        return createdObject;
    }
}

2 Comments

The idea is that I could create this as a singleton in another static class e.g. public static Singleton MySingleton = new Singletion()
You can use the singleton pattern to allow for your interfaces to be implemention independent. Just use a lock when creating the single object

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.