3

I have read many stackoverflow questions on this but phrased differently and not answered what I was looking for. I don't expect any code solutions but a behavioral explanation of singleton object in multi-threaded environment. Answers with some links with explanation would be great.

Question 1: If there are multiple thread that needs to access singleton object(say configured as singleton bean in spring config), then is it that only one thread is able to get access and others are blocked till current holding thread releases it.

For me blocking here makes sense, because there is only one object and all threads cannot get same object at the same time.

So if I configure my DAO as singleton bean then if multiple users(threads) try to do reads and write through that DAO then it doesn't actually happen concurrently but sequentially ---> a performance issue in database intensive application.

On the other hand most of the DAOs are stateless(atleast in my case), so instead of configuring it as Singleton, I can instantiate it wherever I need and do the operations concurrently, but each object instantiation may take some time and memory. So it is a design decision.

In my case, since DAO has no state variable so memory would be negligible, so if my above theory is correct then I would go with 2nd option i.e. choosing concurrency over memory.

Question 2: For the question asked here

I think the best answer is below by S.Lott(I don't know how to point link directly to the answer so copying the answer):

Singletons solve one (and only one) problem.

Resource Contention.

If you have some resource that

(1) can only have a single instance, and

(2) you need to manage that single instance,

you need a singleton.

Here my question is if above answer is true--> That would be the reason for loggers implemented as singletons because you have one log file(single resource).

You don't want that due to time slicing if one thread has written part of some log into the file and then suspended and then thread-2 writes its part and then thread-1 again, thereby making log file gibberish.

I stroke above text because I think if one thread is logging then second thread cannot log at all(blocked) because of singleton config, there by avoiding making log file a gibberish.

Is my understanding right?

Community
  • 1
  • 1
nanosoft
  • 2,164
  • 4
  • 32
  • 50

5 Answers5

2

"Singleton" has no meaning in the Java programming language. It's just a design pattern. The behavior of a singleton object that is shared by many threads is no different from the behavior of any other object that is shared by many threads.

It's safe if, and only if, you make it safe.

Solomon Slow
  • 19,347
  • 4
  • 31
  • 47
2

The quote you have is correct but incomplete. Singleton have more purposes, which hopefully becomes clear later on.

The answer to your first question is, it depends on the bean and how it is implemented. Instances instantiated by Spring do not guarantee thread-safety. For the purpose of answering this question, suppose that there are two possible categories of implementations: stateful and stateless. An implementation can be considered stateful if there are any methods that require external resources (e.g. field variables, database access, file access) that are mutable. On the other hand, an implementation is stateless if all the methods are able to execute their tasks using only their parameters and immutable external resources.

class Stateful {
    private String s; // shared resource
    void setS(String s) {
        this.s = s;
    }
}

class Stateless {
    int print(String s) {
        return s.size();
    }
}

Now, if the implementation is stateless, it generally makes sense for it to be a singleton. Because a stateless class is inherently thread-safe. Multiple threads can use the methods concurrently (without blocking). Just because a class is stateless does not mean that it consumes negligible memory. In Java, instantiating a class is considered an expensive operation.

More work is required for stateful implementations to be a singleton. Again for the purpose of answering this question, suppose that there are two categories of implementation: blocking and non-blocking. Blocking is as described (although there are various types of blocking). Non-blocking means that multiple threads can call the methods concurrently. Typically, there is a thread specially for the non-blocking implementation for processing.

Loggers are good examples of non-blocking implementations. Below is a highly simplified code.

class Logger {
    private List<String> msgs = new CopyOnWriteArrayList<>();
    void log(String msg) {
        msgs.add(msg);
    }
    private void process() {...} // used internally by a thread specially for Logger
}

As for question 2, the basic answer is no; singletons are not all bad. Design patterns are double-edge swords. Use them wisely and they improve your code; use them badly and they create more problems than they solve.

Christopher Z
  • 801
  • 1
  • 7
  • 26
1

Whatever @james said is correct. Coming to your questions:

Question 1: Multiple threads can get access to singleton object without blocking unless you make the get method which returns the object synchronized. Please see below(Multiple threads can get a reference to singleton object without getting blocked).

public class Singleton {
    private Singleton() {
    }

    private static class SingletonHelper {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHelper.INSTANCE;
    }
}

Question 2: No your understanding is incorrect. If one thread is writing, another thread must wait, this is not because of singleton config, but because there might be a possibility that the object(file) may end up in inconsistent state; same is applicable for any object not synchronized properly.

geekprogrammer
  • 836
  • 1
  • 8
  • 37
  • Yeah, I really mixed up Singleton and Synchronization. There is NO reason for threads to be blocked because the methods are NOT synchronized. So concurrent execution of methods on singleton instance(in my case DAO) is certainly not an issue and hence in case of stateless objects using singletons will actually result in good performance because we don't need to create same object again and again. What confused me is -Can multiple thread get reference to same object at the same time. And I think that's what concurrency API does & teaches us to do in thread-safe way for stateful objects.Isn't it? – nanosoft Mar 31 '15 at 16:38
  • 1
    Multiple threads can hold the reference to the same object at the same time. If the program runs on single core processor, than only one thread can execute at any given time, so at any given time, only one thread can get a reference. If the program runs on multi core processor and the get reference method is not synchronized, than yes it is possible that multiple threads can get a reference to the same object at the same time. – geekprogrammer Mar 31 '15 at 17:10
1

you are linking then singleton pattern and a multithread application assuming that the access to the singleton object must be serialized; this is not true.

The requirement is that the singleton must be thread safe.

Consider the DAO example in your question; assuming the each invocation is stateless (i.e. you don't share variables within the class but only witihin the methos) you don't need multiple instance of the same DAO, in a Spring application usually there is one or more manager classes (usually you manage then DB transactions of these manager classes using AOP); each of them has a reference to a single DAO. Each time a DAO object is invoked it gets a DB connection form the data source and it executes the desired operation, then it releases the connection to the data source.

When multiple threads call your manager class you need to acquire/release the DB connection in a thread safe way. Usually Spring hides this complexity and you don't need to worry about that.

A pseudo code for the dao is something like

public void doSomeDBOperation(YourObject param) {
    Connection connection=acquireDBConnection();//the connection must be acquired in a thread safe way
    SQLStatement statement=connection.createStatement(yourSQL);
    //do the operation with your param;
    releaseDBConnection(connection);
}

Spring does sometinh similar under the hood it acquires a Db connection in the AOP aspect, it save in thread local variable so it ca be used by multiple DAOs and you can manage the transaction over the connection.

So one manager, one dao and multiple DB connections is a way to manage multithread operations in parallel (you serialize only the DBconnection lease/release assuming you are using a connection pool) and doing DB operation without blocking (at a java level on the db level things operations may lock in order to guarantee integrity constraints).

Regarding the logger question I assume you are refering to the way most logging library are used i.e you declare a static logger in each of you classes:

public class MyClass {
    private static final Logger logger=LoggerFactory.get(MyClass.class.getName());
    .....
}

The logger class and the file where you log are not directly linked, with Log4J, LogBack, etc you can log to multiple files with one log call, you can even log to something that is not file (a socket for example). The real writing operations are done by the appenders, the appenders must be thread safe and serialize the access to the underlying resource if needed. In you application you declare multiple loggers (one for each class) so there is one singleton per class not only one logger class in you application.

Different threads can invoke the same logger in paralled but it's the underlyng appender guarantees that the access to the underlyng file (o to something else) is serialized if needed (if you have an appender that sends a mail instead of writing a file you can do it concurrently).

Giovanni
  • 3,561
  • 1
  • 19
  • 25
0

If you want to combine multithreading and a single logfile that's not achieved by singletons, singletons only have influence in one thread to avoid another one from popping up.

Now if you break this by using multiple threads, singletons won't help you. If they did, the second thread would just be incapable of logging.

Maarten
  • 7
  • 1
  • edited my original question(see the strikethrough) - I think that's what you meant Only one logging thread can be running and others would be blocked for resource(here singleton logger instance). – nanosoft Mar 31 '15 at 11:48