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?
"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.
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.
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.
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).
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.
Related
I am using spring jdbctemplate in my application and in my query I am using row mapped as new BeanPropertyRowMapper(dto.class)
But I am getting comment from my client to make row mapped thread safe. How it can be done?
The query method looks like:
jdbcTemplate.query(qry, new Object[]("abc"),
new BeanPropertyRowMapper<dto>(dto.class))
Your code is already thread-safe. But you can improve its performance by creating a constant.
The BeanPropertyRowMapper class has mutable data. But once initialized, those data don't change so the class is thread-safe.
Exemple:
private static final BeanPropertyRowMapper<dto> DTO_ROW_MAPPER = new dto<dto>(DtoDetailEvenement.class);
...
jdbcTemplate.query(qry, new Object[]("abc"), DTO_ROW_MAPPER)
Given this code called from a DAO instance method:
jdbcTemplate.query(qry, new Object[]("abc"), new BeanPropertyRowMapper<dto>(dto.class))
(where jdbcTemplate is an instance member of the DAO injected by Spring, and the DAO is a Spring-managed bean with singleton scope) then this seems ok. BeanPropertyRowMapper is stateful and would not be threadsafe if used concurrently by multiple threads, but you're not exposing it to multiple threads, you're using it in a thread-confined manner which is safe.
Java Concurrency in Practice, section 3.3, discusses thread-confinement in general:
Accessing shared, mutable data requires using synchronization; one way to avoid this requirement is to not share. If data is only accessed from a single thread, no synchronization is needed. This technique, thread confinement, is one of the simplest ways to achieve thread safety. When an object is confined to a thread, such usage is automatically thread-safe even if the confined object itself is not [CPJ 2.3.2].
It also discusses (in 3.3.2) the particular kind of thread-confinement that you're doing:
Stack confinement is a special case of thread confinement in which an object can only be reached through local variables. Just as encapsulation can make it easier to preserve invariants, local variables can make it easier to confine objects to a thread. Local variables are intrinsically confined to the executing thread; they exist on the executing thread's stack, which is not accessible to other threads. Stack confinement (also called within-thread or thread-local usage, but not to be confused with the ThreadLocal library class) is simpler to maintain and less fragile than ad-hoc thread confinement.
The only reference to the RowMapper is on the stackframe created for that method call. No other thread (including threads calling the same method on the same DAO) can access it. Tell your client this object is already safe due to being reachable only by local variables, and refer him to the quoted passage from the JCIP book, which is an authoritative reference.
I understand the singleton design pattern concept, but I never really come across implementing singleton pattern in java applications or web based applications.
So tell me where we are using this approach in real time applications.
As described by the pattern, any time you want there to exist only a single instance of something, you would use the Singleton Pattern.
A common example might be a Logger object. There could be many places throughout the system where one would invoke a logger to, well, log something. But you may only ever need one such instance. This can be particularly true if constructing the instance is a heavy operation.
Something like this:
public class Logger {
private static final Logger INSTANCE = new Logger();
private Logger() {
// do something to initialize the logger
}
public static Logger getInstance() {
return INSTANCE;
}
// implementation ...
}
Then any code which needs to reference the logger doesn't need to instantiate it (can't, in fact), and instead just uses the singleton:
Logger.getInstance().Log("some message");
Other real-world examples might include a dependency injection container, a read-only data access service (such as a lookup service which caches results), etc. Generally anything where initialization or repeated operations can be heavy and which is thread-safe.
Singleton always makes sense when dealing with heavy objects where it makes no sense to have more than one instance across the whole application.
Since you are dealing with Web-Applications you should have been dealt with objects which are the same for each user/session/request. Database-Connection-Pool is probably a good example, or a Servlet. It doesn't make sense to create a new Pool for each request. One Pool for the whole application should be sufficient. Other examples are probably Loggers, Email-Client, Global-Settings, those things should be the same instances for each user otherwise you will run out of resources. Or did i get something wrong?
J. Bloch in his Effective Java suggests we use an enum-based singleton implementation. For instance:
public enum Application {
INSTANCE;
//methods, fields
}
This implementation is nice in the case of serialization because enums provide us with the capability of serialization by default (and we don't have to be afraid of getting two different instances while deserializing the object).
My question is how this implementation respects multhreading. How to make it thread-safe? What would we probably get if we try to access it from different threads?
The actual enum behavior of instatiating the instance doesn't have an issue with thread safety. However, you will need to make sure that the instance state itself is thread-safe.
The interactions with the fields and methods of Application are the risk--using either careful synchronization and locking, or purely concurrent data and careful verification that other inconsistencies can't happen, will be your best bet here.
Singleton ensures you only have one instance of a class per class loader.
You only have to take care about concurrency if your singleton has a mutable state. I mean if singleton persist some kind of mutable data.
In this case you should use some kind of synchronization-locking mechanishm to prevent concurrent modification of the state and/or use thread-safe data structures.
I wrote a wrapper around database queries and need to access it from different threads. Therefore my application creates exactly one instance of that helper class and returns it through a getter.
DbConnection dbc = app.getDatabaseConnection();
synchronized (dbc) {
dbc.doSomething();
}
Is this code safe? As stated here it should work although synchronizing on a local variable. Is this correct as long as the object instance is guaranteed to be the same?
Is it a better approach to make all affected instance methods of DbConnection synchronized?
That's not good design.
Instead of making your DBConnection class inherently thread-safe by making its methods/blocks synchronized when necessary, you force all the clients of this class to explicitely synchronize each time it's needed. So instead of encapsulating the thread-safety in a single, well-dentified class, you distribute this responsibility among all the clients of the class, making the whole thing extremely fragile, and a potential bug extremely hard to find out.
That said, using a single database connection from multiple threads is, in itself, a bad idea.
If all your instance methods of DbConnection need to be synchronized, then make all the methods synchronized. Don't look at the amount of code you write, look only at correctness. If you synchronize each method, you don't have a chance of going back years from now and calling getDatabaseConnection then forgetting to synchronize.
I'm trying to create a cache in a webservice. For this I've created a new Stateless Bean to provide this cache to other Stateless beans. This cache is simply a static ConcurrentMap where MyObject is a POJO.
The problem is that it seems as there are different cache objects. One for the client beans, and another locally.
-CacheService
-CacheServiceBean
-getMyObject()
-insertMyObject(MyObject)
-size()
-SomeOtherBean
cache = jndiLookup(CacheService)
cache.insertMyObject(x)
cache.size() -> 1
After this assignment, if I call cache.size from inside the CacheServiceBean, I get 0.
Is it even possible to share static singletons through beans? Finally I decided to use a database table, but I'm still thinking about this.
Thanks for your responses.
As far as I remember you cant be certain that the stateless bean is global enough for you to keep data in static fields. There exist several caching frameworks that would help you with this. Maybe memcache?
EDIT:
http://java.sun.com/blueprints/qanda/ejb_tier/restrictions.html#static_fields says:
Nonfinal static class fields are
disallowed in EJBs because such fields
make an enterprise bean difficult or
impossible to distribute
On the surface, this seems like a contradiction in terms, as a cache is almost certainly something I would not consider stateless, at least in the general sense.
#Stateless
public class CacheSessionBean implements CacheSessionLocal {
private static Map<String, Object> cacheMap = new HashMap<String, Object>();
public Object getCache(String key) {
return cacheMap.get(key);
}
public void putCache(String key, Object o) {
cacheMap.put(key, o);
}
}
The caveats regarding distribution of EJBs in a cluster apply to static variables. However, if you're not clustering, they pretty much don't apply to you, so statics are "okey dokey" at this level.
You WILL have synchronization issues.
One way to mitigate that is to configure your container to only create and pool a single instance of the CacheSession bean, then the container will manage that synchronization for you.
You could also manage the synchronization yourself, but you shouldn't do that at the EJB method level, rather you would likely be better having a synchronized Cache object (vs, say, a generic HashMap).
But the key take away is at this point, static variables are simply static variables.
In theory, you will need to be cognizant of the container lifecycle for your Session Bean (as it can potentially release all instances and thereby the actual bean class could be eligible for GC, thus potentially losing any static data). However, in practice, if the service is popular this is unlikely to happen. But, FYI it COULD happen.
When using stateless beans, you have no control of how many instances of them you have (that's up to your app server to take care of). You could have gotten the output from another bean than the one you looked up from your client. Did you print that in your log? In that case, you maybe should've seen more than one output. The point is that you can't know which instance you get when you look up a stateless bean via jndi (you just get one).
And, you don't have state, so I don't know if this is the best choice for a cache.
By static singleton i suppose you mean a singleton object?
Yes, it shouldn't be a problem to access a singleton through many beans. But remember the concurrency problems you'll probably get. The app server (beans in general) abstracts a lot from you.
I know this post was a while ago but there appears to be a new Singleton Bean that will meet the needs of a cache the original question was aiming at:
http://download.oracle.com/javaee/6/tutorial/doc/gipjg.html
Singleton session beans offer similar functionality to stateless session beans but differ from them in that there is only one singleton session bean per application, as opposed to a pool of stateless session beans, any of which may respond to a client request. Like stateless session beans, singleton session beans can implement web service endpoints.
I've tried creating one and referencing it wo issues from a WebService/Stateless bean. worked as advertised.