1

I want to have a resettable object instance for a session within my program that is thread safe, an example of a session might be a logged in user session.

I am currently doing something like this;

  public final class ObjectFactory {

    private static volatile NativeObjectWrapper instance = null;

    private Singleton() {}

    public static NativeObjectWrapper getInstance() {
        if (instance == null) {
            synchronized(ObjectFactory.class) {
                if (instance == null) {
                    instance = new NativeObjectWrapper(AuthData);
                }
            }
        }

        return instance;
    }

    public void reset() {
      synchronized(ObjectFactory.class) {
        instance = null;
      }
    }
  }

I want to have the object created lazily, with the ability to reset it. Is the above approach threadsafe? if not is there a common pattern to solve this?

An example again would be that scoped object here has some inner data based on the user session and therefore should be a new instance per user session.

Lunar
  • 4,663
  • 7
  • 43
  • 51
  • https://stackoverflow.com/questions/70689/what-is-an-efficient-way-to-implement-a-singleton-pattern-in-java – Malt Oct 30 '19 at 18:27
  • and this: https://stackoverflow.com/questions/46542017/java-singleton-with-an-inner-class-what-guarantees-thread-safety – Malt Oct 30 '19 at 18:27
  • Thats not the same though is it, they are examples of a singleton, not one with the ability to reset it state. – Lunar Oct 30 '19 at 18:29
  • I see. Didn't notice you had a `reset` method. You might want to emphasize it in the question if that's something you need. Generally, singletons are forever. – Malt Oct 30 '19 at 18:31
  • 3
    Do you want a singleton or a session scoped object? This reset business makes me think you have something askew with your design. What does the singleton contain? – Kayaman Oct 30 '19 at 19:05
  • Im hoping for a session scoped object, this object hooks into c code and requires passing authentication data. I need to keep an instance of this object for the lifetime a user is logged in, as its my hook into native C code. Maybe what im really after is some kind of thread safe holder to keep this instance as a scoped object. – Lunar Oct 30 '19 at 20:34

2 Answers2

0

Is the above approach threadsafe?

No, it is not.

Say we have two threads - A and B.

A calls getInstance(), passes the instance==null check, and then there's a context switch to B, which calls reset(). After B finishes executing reset(), A gets the context again and returns instance, which is now null.

if not is there a common pattern to solve this?

I don't remember seening singletons with a reset method, so I'm not aware of any common patterns for this problem. However, the simplest solution would be to just remove the first if (instance == null) check in getInstance(). This would make your implementation thread safe, as instance is always checked and modified within a synchronized block. In this scenario, you could also remove the volatile modifier from instance since it is always accessed from within a synchronized block.

There are more complex solutions I can think of, but I'd use them only if real-world profiling showed that you're spending too much time blocked on that synchronized block. Note that the JVM has some sophisticated ways of avoiding using "real" locks to minimize blocking.

One trickier approach could be to read the instance field just once:

public static Singleton getInstance() {
    Singleton toReturn = instance;
    if (toReturn == null) {
        synchronized(SingletonFactory.class) {
            if (instance == null) {
                instance = new Singleton();
                toReturn = instance;
            }
        }
    }

    return toReturn ;
}

But this could result in returning an old "instance". For example a thread could execute Singleton toReturn = instance and get a valid instance, then lose the CPU. At this point, a 1000 other threads could create and reset 1000 other instances until the original thread gets a spin on the CPU again, at which point it returns an old instance value. It's up to you whether such a case is acceptable.

Malt
  • 28,965
  • 9
  • 65
  • 105
0

Is the above approach threadsafe?

The answer depends on what you think "thread safe" means. There is nothing in your reset() method to prevent a thread that previously called getInstance() from continuing to use the old instance.

Is that "thread safe?"

Generally speaking, "thread safe" means that the actions of one thread can never cause other threads to see shared data in an inconsistent or invalid state. But what "inconsistent" or "invalid" mean depends on the structure of the shared data (i.e., on the design of the application.)


Another way of looking at it: If somebody tells you that a class is "thread safe," then they're probably telling you that concurrent calls to the class's methods by multiple threads will not do anything that disagrees with the class documentation and, will not do anything that disagrees with how a reaonable programmer thinks the class should behave in cases where the documentation is not absolutely clear.

NOTE: That is a weaker definition of "thread safety" because it glosses over the fact that, using thread-safe components to build a system does not guarantee that the system itself will be thread-safe.

Does everybody who uses your class clearly understand that no thread in the program may ever call reset() while any reference to the old singleton still exists? If so, then I would call that a weak design because it is very far from being "junior-programmer-safe," but I would grudgingly admit that, from a strict, language-lawyerly point of view, you could call your ObjectFactory class "thread safe."

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57