Pergunta

Eu tenho uma classe Java que é usado em um multithreading aplicação.Acesso simultâneo é muito provável.Simultâneas múltiplas operações de leitura não deve bloquear então, eu estou usando um ReadWrite de bloqueio.

class Example {
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private int i;
    private boolean b;

    public int getI() {
      lock.readLock().lock();
      final int tmp = i;
      lock.readLock().unlock(),
      return tmp;
    }

    public void setI( final int i ) {
      lock.writeLock().lock();
      this.i = i;
      lock.writeLock().unlock();
    }

    public boolean getB() {
      lock.readLock().lock();
      final boolean tmp = b;
      lock.readLock().unlock(),
      return tmp;
    }

    public void setB( final boolean b ) {
      lock.writeLock().lock();
      this.b = b;
      lock.writeLock().unlock();
    }
}

Para simplificar, eu deixei de fora a try...finally os blocos ao redor os bloqueios neste exemplo.

Eu estou querendo saber se é necessário (ou, digamos, recomendadas) para bloquear/sincronizar getters e setters de tipos primitivos?Eu sei que atribuir e operações de devolução em Java são atômica.No entanto, ao usar esses bloqueios não ter certeza de que cada acessor obtém o valor mais recente (igual ao utilizar volatile)?

O que se as primitivas foram double ou long?

Foi útil?

Solução

Isso depende.

Note, no entanto, que, normalmente, você precisa para sincronizar as operações em mais de granulação grossa nível, por exemplo, este:

Example e = ...;

synchronized (e) {
    e.setI(e.getI() + 10);
}

Para tais situações, seus bloqueios internos são redundantes.Portanto, talvez seria melhor aplicar a sincronização externa onde você usar esses objetos, em vez de sincronização interna.

Outras dicas

você tem algo como AtomicInteger em java, que funciona bem com o Aplicativo Multithread.

Pergunte a si mesmo se esta classe pode ser implementada como uma classe imutável.Será mais fácil para se trabalhar, e vai ser inerentemente thread-safe.Você não terá de se preocupar com a concorrência, bloqueios, sincronização, etc.

Exemplo de uma classe imutável:

final class Example {
    private final int i;
    private final boolean b;

    public Example(int i, boolean b){
        this.i = i ;
        this.b = b;
    }

    public int getI() {
        return i;
    }

    public boolean getB() {
        return b;
    }
}

Gostaria de projetar seu aplicativo para que você não vai ter acesso simultâneo a um tipo de dados raw como este.Adicionar como baixo nível de fecho é susceptível de diminuir a sua aplicação tanto é que não vale a pena multi-threading o seu aplicativo.

exemplo:Digamos que você tenha uma versão de 32 núcleo do sistema que balança perfeitamente e é executado 32x mais rápido do que em 1 de núcleo.No entanto, um campo de acesso sem fecho leva 1 ns, com fecho leva 1-nos (1000 ns) então, no final de sua aplicação pode demorar ~30x mais lento.(1000 mais lentos / mais rápido de 32) Se você tiver apenas 4 núcleos, pode ser centenas de vezes mais lento, derrotando o propósito de ter multi-threads em primeiro lugar.IMHO.

Não é necessário bloquear/sincronizar getters e setters de tipos primitivos - marcá-los como volátil é suficiente na maioria dos casos (para além do duplo e por muito tempo como você mencionou)

Como um dos posts anteriores menciona, você precisa estar ciente de leitura e atualização de sequências, algo como incrementI(int num), que provavelmente vai se chamar getI() e setI() - neste caso, você poderia adicionar um 'sincronizado incrementI(int num)" método para o seu Exemplo de classe.Fecho, em seguida, é feito em um nível mais alto, reduzindo a necessidade de separar ler e escrever bloqueios e é OO do ambiente de dados e o comportamento de ficar juntos.Esta técnica é ainda mais útil se você está a ler/atualizar vários campos de uma só vez.

Mas se você estiver simplesmente, leitura/escrita/atualização de um campo de cada vez, em seguida, o AtomicXX classes são mais apropriados

Você não deve usar o bloqueio de tipos primitivos, de Seqüência de caracteres (eles são imutáveis) e thread-safe tipos (como coleções de "concorrentes" pacote).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top