The problem with the code is that if there is more than one concurrent call on first access to the method getInstance()
it can create two Test instances.
The basic solution for this is to synchronize the method:
public static synchronized Teste getInstance()
{
if ( INSTANCE == null )
{
INSTANCE = new Teste();
}
return INSTANCE;
}
The problem with this approach is that all calls will be blocked, slowing the overall execution of the program. Imagine such a method on an application server with multiple users accessing the system? Terrible.
A better solution would be a block synchronized
within the IF
:
public static Teste getInstance()
{
if ( INSTANCE == null ) {
synchronized (Teste.class) {
INSTANCE = new Teste();
}
}
return INSTANCE;
}
This solves the problem of synchronization in all accesses, but it is a "naive" solution, because we actually returned to the initial problem. Like the IF
is not synchronized, two threads
can enter the IF
at the same time and even with synchronization, they will return different instances when INSTANCE
for null
.
So the most "pure" solution for Singleton Pattern would be to add a double check, thus:
public static Teste getInstance()
{
if ( INSTANCE == null ) {
synchronized (Teste.class) {
if ( INSTANCE == null ) {
INSTANCE = new Teste();
}
}
}
return INSTANCE;
}
With this last approach, we guarantee that there will be no loss of performance because of unnecessary synchronization of the entire method.
In addition, we ensure that even if two competing calls to the method come within the first IF
, then we have a new synchronized check that guarantees a single Test instance.
So in the worst case, if there are two or more competing calls on first access to getInstance
(when INSTANCE
is still null
), only these first calls will be synchronized, and after the first assignment of INSTANCE
, no subsequent call will be synchronized.
A full read on this you find on
Head First Design Patterns.
I recommend you research on Singleton
Note: the constructor private
prevents any other class from inadvertently or arbitrarily creating an unwanted Test instance.
Como o construtor está privado ele nunca será chamado.
this conclusion is not correct, if the constructor is private, it is only accessible within the class itself.– user28595
Your 4 conclusions are wrong.
– Maniero
Teste
in a competing environment. My question on Soen (in English) discusses some of the classic solutions for Concurrent Lazy-loading: https://stackoverflow.com/q/6189099/664577– Anthony Accioly
The biggest problem there is the question asked. The code does not fear anything wrong. If in addition to the code the teacher had passed that it would run in a situation that could be created concurrently and what is the problem of design of this code, then you could answer it better. When the question is bad, the answer gets complicated. That is why it is common for programmers to suffer to create solutions, before solving need to know well what the problem is, need to ask the right question. (I am not talking about this question put here, which is good for a beginner, despite the wrong conclusions)
– Maniero
Considering the answer you accepted, read this: https://www.cs.umd.edu/~Pugh/java/memoryModel/Doublecheckedlocking.html
– Victor Stafusa