Pergunta

Eu preciso de um balcão de tipo long Com os seguintes requisitos/fatos:

  • Incrementar o contador deve levar o mínimo de tempo possível.
  • O contador será escrito apenas por um tópico.
  • A leitura do balcão será feita em outro tópico.
  • O contador será incrementado regularmente (até alguns milhares de vezes por segundo), mas só será lido uma vez a cada cinco segundos.
  • A precisão precisa não é essencial, apenas uma idéia aproximada do tamanho do contador é boa o suficiente.
  • O contador nunca é limpo, diminuído.

Com base nesses requisitos, como você escolheria implementar seu contador? Como simples long, como um volatile long ou usando um AtomicLong? Por quê?

No momento eu tenho um volatile long Mas estava se perguntando se outra abordagem seria melhor. Eu também estou aumentando o meu tempo fazendo ++counter em oposição a counter++. Isso é realmente mais eficiente (como fui levado a acreditar em outros lugares) porque não há nenhuma tarefa?

Foi útil?

Solução

Dados esses conjuntos de requisitos, eu acho que um volatile por muito tempo deve ser suficiente. O contador não estaria incorreto com um nãovolatile Long, mas o leitor pode estar lendo informações obsoletas nesse caso.

Um problema é que lê e escreve para um long são não requeridos ser atômico, pelo Especificação JVM Se não for declarado volatile. Isso significaria que o thread de leitura poderia obter um valor praticamente fictício se lê o valor enquanto o tópico de escrita atualizou uma parte do valor, mas não a outra.

A diferença entre ++counter e counter++ é provavelmente irrelevante, como a JVM perceberá que o valor da expressão não é mais usado e os dois são equivalentes neste caso.

Outras dicas

No Java 8, use Longadder, que é ainda melhor que o atômico, onde a contenção de roscas é alta.

Longadder Javadoc:

Essa classe é geralmente preferível a atômico quando vários threads atualizam uma soma comum usada para fins, como coleta de estatísticas, não para controle de sincronização de granulação fina. Sob baixo contenção de atualização, as duas classes têm características semelhantes. Porém, sob alta contenção, a taxa de transferência esperada desta classe é significativamente maior, às custas de maior consumo de espaço.

Qual é o requisito de tempo de atividade para o seu programa? Você poderia se contentar com uma INT não volátil e leituras racy?

10^4 incrementos / segundo é 1 a cada 100 USEC. A eficiência não é um problema, mas a atomicidade pode ser. Você pode ter 2 cópias e, quando é lido, se não forem iguais, leia novamente.

este artigo fala sobre as possíveis maneiras de implementar um contador, acho que essa implementação deve funcionar para você

class LessNaiveVolatieIdGenerator {
private static volatile long id = 0;
public static long nextId() {
    long nextId = (id = id + 1); // or nextId = id++;
    return nextId;
}

}

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