Pra que serve o Double-checked locking?! Alguem usa mesmo isso? A meu ver não há nenhuma vantagem sobre sincronizar todo o metodo assim:
public static synchronized Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
Que é como geralmente faço. E mais, se eu não usar lazy instantiation para criar o singleton, ou seja, se eu o criar quando a classe é carregada, parece-me que double-checked locking fica mais inutil ainda. Então, alguem pode me explicar se (e quando) se deve usar essa tecnica?
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
tem um post sobre DoubleCheckedLocking aqui no Guj…dá uma
pesquisada.Honestamente,não vejo muitas vantagens…
pow,se vc não sincronizar vc pode ter 2 instancias dele,e,
sincronizando tem problemas críticos de concorrência…
DoubleChecked locking era um truque para se ter lazy initialization a um custo muito baixo em um ambiente muiti-threaded. Isso, porem, dificilmente funciona com as cpu’s modernas sem um certo esforço.
A situação é mais grave pelo fato do java não possuir primitivas de memory e code barriers. Ou seja, double-checked locking em java é 1 grande armadilha.
No java, a única solução de sincronização que funciona são os monitores, nada alem disso vai funcionar, não ao menos sem possuir um custo maior que o dos próprios monitores.
Isso se deve ao fato de java não te dar acesso a alguns recursos indispensaveis para se criar primitivas de sincronização rápida em user space; alguns exemplos são intruções atomicas de teste-operação (test-and-set e test-and-complement são algumas disponiveis em pc’s) ou troca atomica registrador-memoria, não temos um increment, não tem suporte a code ou memory barriers ou ainda ter permitir alinhar um objeto na memoria de acordo com as cache-lines de uma cpu.
Paulo, eu acho que voce ta confundindo a primitiva de sincronização barrier, com code e memory barriers, que são artificios, normalmente instruções, para garantir de forma precisa o comportamento de 1 pedaço de código. Voce se refereria ao java.concurency ne?
Code barriers possuem 2 tipos de garantia, uma o compilador não vai fazer scheduling de instruções ou otimizações atravez da barreira (blocos volatile asm no gcc); outra garante ordem de execução de instruções pelo processador, todas instruçoes que vem antes da barreira são retired antes, todas que vem depois são retired depois (a instrução ‘cpuid’ dos pc’s).
Memory barriers impoem ordenação no acesso de memoria, ou seja, uma write-barrier, impõe que todas operações de escrita devem ser completas antes da barreira ser antingida; o mesmo vale para read-barriers.
mas falaram que agora, arrumando o modelo teorico de memoria do java, e tendo as barriers no concurrent, da para fazer o lazy init soh syncing o lazy init e tal.
Paulo, eu olhei o javadoc do ultimo draft do JSR 166, e nele não existe nenhuma referencia a barreiras. Existem as variaveis atomicas, que te permitem implementar thin-locks com busy-wait, mas memory barriers não achei 1 unica referencia se quer, que seria necessario para implementar lazy-init de forma segura.
Porem não cheguei a ver quais alterações tão sendo feitas no modelo de memoria do java.
Sei nao… eh mais um desses casos onde um cara nao gosta de determinada coisa e fica procurando motivo pra convencer o resto do pessoal a nao usar. Dae sempre aparece alguem com “100 motivos para usar X”, e logo em seguida tem outro postando “200 motivos para nao usar X” e assim vai…
Eh meio phoda isso… voce ( “voce” nesse caso nao eh ninguem aqui em especial, apenas o sujeito ) acha determinada funcionalidade ruim, e o teu colega acha legal… eh soh perda de tempo tentar forcar a outra pessoa a deixar de usar simplesmente porque voce nao gosta… mesmo que de todos os pontos do mundo, se nao mostrar com fatos e de uma maneira explicativa e nao-agressiva, a pessoa nunca ira aceitar o seu ponto de vista, entrando em uma discussao ideologica inutil.
Eu uso Singletons para casos onde nao ha fundamento em processar a mesma coisa sempre de novo ( como arquivos de I18n, por exemplo )… chamo de Singleton porque tudo mundo chama, mas no fundo, to nem ai para o nome… se a funcionalidade atende os meus requisitos, perfeito, e dane-se o resto.
Deixar de usar alguma coisa ou fazer de outra maneira soh porque “eh conceitualmente errado” eh besteira… Mas nao me interpretem mal: nao estou dizendo que fazer da * maneira* errada eh algo que tenha o meu apoio, mas sim que se for algo puramente conceitural - como esse monte de regras de OO - prefiro fazer da maneira que funcione melhor e que atenda aos requisitos, do que fazer apenas para deixar algumas pessoas felizes…
Nem sempre isso acontece… primeiro o fácil:
duardor, bota “util.concurrent” no google e acha a página do Doug Lea. Esse pacote vai entrar no java 1.5
Segundo, os singletons. tem um cara aqui na empresa que é louco por patterns, e a gente briga sempre pq o primeiro site que ele vai buscar teoria é o TheServerSide, e depois o da Sun. Eu busco teoria no Wiki do C2.
Entao eu venho com essas idéias de Yagni, OnceAndOnlyOnce, e bla bla bla, e ele me mostra um exemplo de “Factory pra usar DAOs como ValueObjects”, que era exatamente o que a gente estava implementando.
E a gente comecou a discutir pq eu queria que o objeto tivesse IoC (e por isso ia precisar de um construtor com argumentos), e a Factory da Sun obrigava os objetos a terem construtores vazios.
Logicamente, como eu implementei o objeto, eu botei o argumento e falei “se vira”, e a factory agora contém o código pra inicializar o argumento, em vez de eu ter que fazer isso no meu construtor.
Discussoes como essa sempre aparecem relacionadas a Singletons e padroes para os quais existe um “exemplo” da Sun. (ou seja, todos).
O que eles vao mudar no modelo teorico de memoria pra 1.5??
Pra isso que vc usa Singletons (arquivos i18n, no exemplo que vc citou), um método estático tava mais do que bom…e, se vc for olhar bem, pra grande maioria das coisas onde se usaria um singleton, um ‘static’ bem colocado já resolveria o problema muito bem.
Eu concordo com vc - briguinhas do tipo “X nao presta”, “X presta”, “nao presta não!”, “presta sim!” são meio babacas. Mas, se vc pensar bem, é nesse tipo de discussão que a gente tira as melhores idéias. Se X não presta, como a gente pode melhorar? Quais são as alternativas? E por aí vai. Eu não queria começar uma discussão besta com o meu post - eu queria uma discussão sobre as alternativas aos Singletons, que em muitos casos (cough i18n cough) são utilizados indevidamente.
tipo, eu utilizava um Singleton para por exemplo, um objeto de acesso ao hibernate, mas era por falta de conhecimento, depois que resolvi ler a docume’ntação e descobri que o session do hibernate não era thread safe, acabei transformando os Singletons neste caso, em factories ou multitons
para i18n, normalmente utilizo um ResourceBundle normalmente, nem estatico é, e nunca tive problemas com alocação de memoria por causa disto
nunca tinha pensado desta maneira, mas este artigo com certeza me fez pensar
Voce esta julgando as coisas sem conhecer o codigo usado. Claro que muitas vezes um static xxx meuMetodo da pro gasto, mas E DAI se eu quiesse colocar um getInstance()?
Por exemplo, o metodo para pegar determinada mensagem eh estatico, mas o metodo para dar reload no arquivo .properties nao. Por que? eu simplesmente quis fazer assim, meter static em tudo nao me agradava, entao criei uma instancia privada para ter acesso as partes nao-static.
Como disse na outra mensagem, se chegar pro codigo do cara e dizer “AARGGHH, isso aqui nao tem nada a ver, tinha que ter usado tudo static” soh vai deixar a pessoa humilhada e constrangida.
Eu não estou tentando te atacar ou julgar. Estou tentando levantar uma discussão construtiva sobre o uso (especificamente, o mal-uso) de singletons. Não leve o que eu estou escrevendo tão a sério, ou como uma afronta pessoal - de forma alguma é a minha intenção.
Eu lasco esses "AAAAAARGH"s bem frequentemente, apesar de - eu acho - ser um pouco mais discreto
O curioso é que, ao invés de olhares humilhados e constrangidos, geralmente eu sou recebido com um “mas pq?”, que geralmente são bem mais construtivos, e geram uma discussão bastante interessante
Bom, dos artigos recomendados, a citação que mais me chamou atenção foi…
… encontrada nesse artigo e que acessei atraves desse outro. Não uso singletons a todo momento, mas, em alguns casos parece-me ser a alternativa mais interessante, por exemplo, um pool de conexões. Não dá pra ficar criando o pool a todo instante. Entretanto, ao que parece, a alternativa sugerida seria colocar o pool como um atributo estatico em algum canto, é isso? Algo como:
public class ClasseQualquer {
public static Pool pool = new Pool();
...
}
Era mesmo isso? Se for, não vejo qual a vantagem. Já que eu poderia fazer o singleton assim:
public class Pool {
private static Pool pool = new Pool();
...
public static Pool getInstance() {
return pool;
}
}
Sobre o overhead que terei quando sincronizar o getInstance, li nesse artigo, recomendado nesse post, que o custo da sincronização nas jvms mais modernas não é tão grande assim. É claro, se eu tiver uma quantidade muito grande de threads acessando o getInstance, um pequeno overhead pode se transformar numa grande espera. Mas, acho que dá pra continuar usando o singleton se eu não usar lazy initiation como no exemplo acima ou eu posso rever algumas coisas e transformar o singleton numa factory, acho. :?
Eu também solto esses AAAARGH, e nem sempre o pessoal gosta. Quando eles aprendem que nao é com eles, e que geralmente eu faco AARGH quando vejo um código igualzinho ao que eu mesmo um dia escrevi e me deu tanto trabalho depois, eles páram de se ofender. Mas de uns tempos pra cá, tenho tomado mais cuidado.
Muito código que eu geralmente critico eu mesmo já escrevi igual um dia. Outras vezes, é coisa que eu nunca vi, e nunca tive a inspiracao para fazer assim. Nesses casos, quando o outro cara é bom na discussao, eu aprendo alguma coisa.
Meus AAARGHs geralmente promovem melhor software, ou pq o cara aprende alguma coisa, ou pq eu aprendo alguma coisa. Nunca, mas nunca mesmo, eu avalio um programador pelo código que ele escreve, mas pelo quanto ele é capaz de defendê-lo (nos pontos bons) e aprimorá-lo (nos pontos ruins) numa discussao. Pq eu preciso confiar no código dele, e ele no meu.
Eu chamo de singleton uma instância única. Mas essa instancia tem que ser acessada de alguma forma, e nem sempre a melhor forma é um método estático na classe, com construtor privado. Eu penso em componentes, e sei que um dia vou poder precisar de mais de uma daquela instância. Hoje que eu aprendi IoC eu posso fazer assim:
public class Application {
public Application(MeuExSingleton instancia) {
...
}
...
public static void main(String args[]) {
MeuExSingleton mes = new MeuExSingleton();
Application app = new Application(mes);
app.start();
}
}
eu tambem prefiro sempre singleton. A sun ja cagou pra caramba em fazer a System e a Math tudo estatico. Se a math fosse um singleton, a gente poderia fazer Math.getMath(“normal”) ou Math.getMath(“strictl”) por exemplo. Pois hoje em dia a gente tem de trocar tudo que eh Math para StrictMath. Pessimo.
Mas a definicao que o cancao deu eh otima. use singleton se a classe possui um estado. Essa regra deve ser sempre obedecida. E mesmo se ela nao valer (caso da math), as vezes tambem eh interessante usar singleton.