Problema com lock?

2 respostas
F

Fala, galera.
Seguinte, eu tô com uma situação que tá meio chata de resolver, mas o meu feeling (de iniciante haha) me levou a essa dúvida dos locks.
A situação é a seguinte (copiado de um e-mail que mandei pra um amigo):

no programa, eu tenho o lançamento de despesas e receitas e transferências.
ok. tá tudo certo com a lógica das operações, mas às vezes a conta bancária não é atualizada.

exemplo: eu tenho 1000 reais na “BR” e insiro uma saída de 500.
a conta “BR” deve ficar com 500. o problema é que às vezes o banco não atualiza a conta. é quase que aleatoriamente (embora eu saiba que há algo errado).

outro dia, tavam fazendo lançamentos e eu tava acompanhando as contas. tudo corria bem e de repente, deu uma diferença.
aí, como eu sabia que o código estava certo, resolvi aguardar. e depois de uns 2 minutos, o banco atualizou as contas.

será algo do postgres?
já fiz inúmeros testes aqui, inclusive tentando gerar excessões antes de fazer as operações, mas nada…

Esse amigo acha que é um caso de condição de corrida e me passou links sobre optimistic lock e pessimistic lock. Estou lendo sobre eles agora, e tentando aplicá-los corretamente.
Porém, eu quero ver outras opiniões.

PS: É um sistema desktop, então acho que é uma situação mais fácil de ser resolvida.

abraço!

2 Respostas

nel

Não é “achar”, é com certeza problema de corrida.
Esse algoritmo para trabalhar com conta bancária tem centenas de implementações, se pesquisar aqui no GUJ, tu vai encontrar soluções muito boa !!

O que ocorre é que provavelmente tu não está garantindo que os métodos serão invocados na ordem correta.
Um exemplo, é você mandar depositar e em seguida sacar. Se não tiver garantias que já foi depositado, você terá problemas.
Vai que por algum motivo o método de deposito seja lento e demore a terminar e nesse tempo, o método de saque ocorre.

É só um exemplo. Procure sobre o modificador synchronized, ele que vai resolver teu problema, a princpio.

F

O que me intriga é que mesmo com apenas um usuário (o que garante a ordem dos métodos) e sem ocorrerem excessões, às vezes o banco não atualiza a conta. Nesse caso não pode ser um problema de condição de corrida. Só poderia ser um problema de lógica, uma excessão (que não ocorre, pelo que mostram os logs) ou um problema do banco em si, o que acho muitíssimo improvável.

O código:

ActionPerformed do action de inserir uma receita

@Override
	public void actionPerformed(ActionEvent e) {
		if (new ValidadorEntrada(tela).validarCampos()) {
			try {
				entidade = (MovimentoDeEntrada) tela
						.gerarEntidade();
				Conta conta = entidade.getConta();
				if (entidade.isRealizado()) {
					conta.depositar(entidade.getValor());
				}
                //new DAOConta().atualizar(conta); // indiferente por causa do @Cascade(CascadeType.SAVE_UPDATE)
				dao.salvar(entidade);
				tela.adicionarItemTabela(entidade);
			} catch (Exception exc) {
				exc.printStackTrace();
			}
		}
	}

Método depositar da classe Conta

public void depositar(BigDecimal valor) {
    	qtdCaixa = qtdCaixa.add(valor);
    }

Método salvar do dao genérico

public void salvar(T entidade) {
        if (entidade == null) {
            throw new IllegalArgumentException();
        }
        Session sessao = pegarSessao();
        Transaction transacao = sessao.beginTransaction();
        try {
            sessao.saveOrUpdate(entidade);
            transacao.commit();
        } catch (ConstraintViolationException e) {
            transacao.rollback();
            throw e;
        } finally {
            sessao.close();
        }
    }
Criado 30 de abril de 2012
Ultima resposta 30 de abr. de 2012
Respostas 2
Participantes 2