Estou fazendo um stateless bean que possui 2 métodos que têm conflito: ambos acessam um objeto e o atualizam. Seria mais ou menos assim:
public void method (String key, int newValue) {
Object obj = Cache.getObject(key);
obj.setBla(newValue);
Cache.updateObject(key, obj);
}
Então ambos métodos pegam uma instância de um objeto que está armazenada num repositório e o modifica. Um dos métodos é chamado o tempo todo, o outro quase nunca. Porém ambos não podem ser executados simultaneamente (pelo menos não com a mesma instância - mesmo key).
- Como solucionar o problema? Sincronizar os dois médotos vai matar o desempenho, a classe é um stateless bean e um dos métodos é chamado com grande frequencia...
- Existe uma maneira de usar a instância do obj como lock da sincronização e assim fazer com que os 2 métodos possam ser executados simultaneamente exceto quando os obj possuem a mesma key?
nao sei se entendi a pergunta mas uma ideia seria usar um bloco sincronizado dentro do metodo ao inves de sincronizar o metodo por exemplo sincronized(meuObjeto){ …} , talvez metodos como wait e notify possam ajudar
fantomas
Acho q não entendi direito. Vc tem 2 métodos executando este método que vc citou, é isso?
Outra coisa neste método q vc escreveu, acho que não precisa do Cache.updateObject(key,obj) caso ele esteja retornando apenas a referencia do obj, se for um novo ai beleza.
Diz ai…
flws
otavio
Na verdade quem tem que ser sincronizado é teu objeto e não o método.
Sincronizar o método vai controlar o acesso no método, não no objeto. Mas… lembre-se que usar atributos static nos EJBs e modificar instâncias viola a especificação, pois caso for usado cluster você vai alterar o valor desse objeto apenas no nó corrente.
roberto_sc
Explicando melhor:
São 2 métodos diferentes no mesmo EJB, esse método que eu postei é só um exemplo de como mais ou menos eles são. Estes dois métodos podem ser executados simultaneamente e modificar o obj, e daí vem o problema.
O Cache implementado aqui funciona assim, é necessário o update mesmo.
Obrigado pela dica do static, nós realmente vamos usar cluster!
Pensei que uma solução seria fazer isso, em cada um dos 2 métodos:
publicvoidmethod(Stringkey,intnewValue){syncronized(obj){//hmm that wont work... :(Objectobj=Cache.getObject(key);obj.setBla(newValue);Cache.updateObject(key,obj);}}
Mas isso não vai funcionar, certo?
M
marcobiscaro2112
Tente inverter as linhas: primeiro você pega um objeto do Cache, e usa-o como lock para a mudança que deve ser sincronizada. E observe a dica de fantomas. Algo como:
publicvoidmethod(Stringkey,intnewValue){Objectobj=Cache.getObject(key);syncronized(obj){obj.setBla(newValue);Cache.updateObject(key,obj);// essa linha será realmente necessária?}}
Não tenho certeza, mas acho que isso pode ajudar.
Lavieri
se o seu problema especifico é so nesses 2 metodos… e so quando os 2 ocorrem simultaneamente…
e vc tem 1 método que é menos frequente… coloque o sync apenas no método menos frequente… e so na parte do uso do objeto… isso para priorizar o desempenho… assim vc so vai travar o objeto, quando estiver usando o método menos frequente, ou seja… e talvez ajude no seu desempenho…
M
marcobiscaro2112
Lavieri:
se o seu problema especifico é so nesses 2 metodos… e so quando os 2 ocorrem simultaneamente…
e vc tem 1 método que é menos frequente… coloque o sync apenas no método menos frequente… e so na parte do uso do objeto… isso para priorizar o desempenho… assim vc so vai travar o objeto, quando estiver usando o método menos frequente, ou seja… e talvez ajude no seu desempenho…
Mas isso pode dar problema… pense comigo:
O metodo1() é o chamado com frequência enquanto o metodo2() é chamado só as vezes. Na execução do programa teríamos uma sequência de chamadas como, por exemplo:
Acontece que o metodo2, nesse caso, conseguirá tranquilamente o lock do objeto, uma vez que o metodo1 não é sincronizado (ou seja não requer o lock de objeto algum). Com isso, a execução do metodo1 seria interrompida no meio, o metodo2 seria todo executado e a execução do metodo1 seria retomada, dando inconsistência nos dados. Creio que os dois métodos devem ter um trecho sincronizado para evitar problemas como esse.
Lavieri
verdade… melhor dar um shync nos 2 mesmo
otavio
A opensynphony possui uma lib para cache que é a Oscache, que suporta cluster e tudo mais. Não conheço o teu projeto, mas creio que usar uma lib com a Oscache é uma boa, pois ela é bem testada e até o Hibernate usa ela.
A lib ehcache não possui suporte a cluster se não me engano.
Creio que usando uma lib dessas você pode trabalhar melhor nas regras de negócio e deixa que a Oscache faça o trabalho pesado
roberto_sc
Obrigado pessoal.
Nos estamos usando o POJO Cache da JBoss, vcs sabem se ele tem alguma coisa para cuidar dessa parte de lock dos objetos?