Pergunta

Digamos que você tenha a seguinte classe

public class AccessStatistics {
  private final int noPages, noErrors;
  public AccessStatistics(int noPages, int noErrors) {
    this.noPages = noPages;
    this.noErrors = noErrors;
  }
  public int getNoPages() { return noPages; }
  public int getNoErrors() { return noErrors; }
}

e executar o seguinte código

private AtomicReference<AccessStatistics> stats =
  new AtomicReference<AccessStatistics>(new AccessStatistics(0, 0));

public void incrementPageCount(boolean wasError) {
  AccessStatistics prev, newValue;
  do {
    prev = stats.get();
    int noPages = prev.getNoPages() + 1;
    int noErrors = prev.getNoErrors;
    if (wasError) {
      noErrors++;
    }
    newValue = new AccessStatistics(noPages, noErrors);
  } while (!stats.compareAndSet(prev, newValue));
}

No while (!stats.compareAndSet(prev, newValue)) última linha como é que o método compareAndSet determinar a igualdade entre prev e newValue? É a classe AccessStatistics necessário para implementar um método equals()? Se não, por quê? O javadoc afirma o seguinte para AtomicReference.compareAndSet

atomicamente define o valor para o determinado valor atualizado se o valor atual == o valor esperado.

... mas esta afirmação parece muito geral e os tutoriais que eu li sobre AtomicReference não sugerem a implementação de um equals () para uma classe envolto em uma AtomicReference.

Se as classes envolvidas em AtomicReference são obrigados a implementar equals (), em seguida, para objetos mais complexos do que AccessStatistics Eu estou pensando que pode ser mais rápido aos métodos sincronizar esse update do objeto e não usar AtomicReference.

Foi útil?

Solução

Ele compara os refrerences exatamente como se você tivesse usado o operador ==. Isso significa que as referências devem estar apontando para a mesma instância. Object.equals () não é utilizado.

Outras dicas

Na verdade, ele faz não prev comparar e newValue!

Em vez disso, compara o valor armazenado dentro estatísticas para prev e somente quando aqueles são os mesmos, ele atualiza o valor armazenado dentro estatísticas para newValue. Como dito acima que utiliza o operador (==) para fazê-lo é igual. Isto significa que anly quando prev está apontando para o mesmo objeto que é armazenado nas estatísticas irá estatísticas ser atualizado.

Ele simplesmente verifica a igualdade de referência de objeto (aka ==), então se referência de objeto realizada por AtomicReference tinha mudado depois que você tem a referência, não vai alterar a referência, então você vai ter que começar de novo.

A seguir estão algumas do código-fonte de AtomicReference. AtomicReference refere-se a um objecto de referência. Esta referência é um membro variável volátil no exemplo AtomicReference como abaixo.

private volatile V value;

get () simplesmente retorna o último valor da variável (como voláteis fazer em um "acontece antes" forma).

public final V get()

A seguir é o método mais importante de AtomicReference.

public final boolean  compareAndSet(V expect, V update) {
        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}

O compareAndSet (esperar, atualização) método chama o método compareAndSwapObject () da classe inseguro de Java. Esta chamada de método de invoca inseguras a chamada nativa, que invoca uma única instrução para o processador. "Espera" e "update" cada referência um objeto.

Se e somente se a variável "valor" membro de instância AtomicReference refere-se ao mesmo objeto é referido por "esperar", "update" é atribuído a essa variável de instância agora, e "verdadeiro" é retornado. Ou então, false é retornado. A coisa toda é feito atomicamente. Nenhum outro segmento pode interceptar no meio. Como se trata de uma única operação do processador (magia da arquitetura do computador moderno), é muitas vezes mais rápido do que usando um bloco sincronizado. Mas lembre-se que quando múltiplas variáveis ??precisam ser atualizados atomicamente, AtomicReference não vai ajudar.

Eu gostaria de adicionar um código de execução de pleno direito, que pode ser executado em eclipse. Ele iria limpar muitos confusão. Aqui 22 usuários (threads mito) está tentando reservar 20 lugares. A seguir está o fragmento de código seguido do código completo.

Código trecho onde 22 usuários estão tentando reservar 20 lugares.

for (int i = 0; i < 20; i++) {// 20 seats
            seats.add(new AtomicReference<Integer>());
        }
        Thread[] ths = new Thread[22];// 22 users
        for (int i = 0; i < ths.length; i++) {
            ths[i] = new MyTh(seats, i);
            ths[i].start();
        }

A seguir está o link github para quem quer ver o código completo em execução que é pequeno e conciso. https://github.com/sankar4git/atomicReference/blob/master/Solution. java

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