[Programação Concorrente] --- Compare e swap (CAS) Análise Princípio

Fonte Endereço: https://github.com/nieandsun/concurrent-study.git


1 O que é CAS?


1,1 CAS princípios diferentes de bloqueio e resolver o problema de atomicidade

Primeiro, olhe para o seguinte código:

package com.nrsc.ch2.cas;

import java.util.ArrayList;
import java.util.List;

public class CasDemo {

    //共享资源
    static int i = 0;

    public static void increase() {
        i++;
    }

    public static void main(String[] args) throws InterruptedException {
        Runnable r = () -> {
            for (int j = 0; j < 1000; j++) {
                increase();
            }
        };

        List<Thread> threads = new ArrayList<>();
        for (int j = 0; j < 10; j++) {
            Thread thread = new Thread(r);
            threads.add(thread);
            thread.start();
        }

        //确保前面10个线程都走完
        for (Thread thread : threads) {
            thread.join();
        }

        System.out.println(i);
    }
}

Eu acredito que todo mundo sabe o código devido i++不是原子操作, levando assim ao resultado final dos 10 threads de execução de 10 * 1000 = 10.000.
Claro, eu acredito que quase todo mundo sabe por 加锁可以解决这个问题, princípio de bloqueio para resolver o problema básico pode ser perfilado usando a figura seguinte:
Aqui Insert Picture Descrição
mas, na verdade, além do uso de mecanismo de bloqueio CAS pode resolver este problema. Além disso, uma vez que está bloqueado Outra solução, 那它肯定是无锁的e, portanto, o uso de mecanismo de CAS para resolver o problema de maneira pode ser grosseiramente perfil com a figura a seguir:
Aqui Insert Picture Descrição
que no final o que é CAS? Como ele faz para resolver este problema?


1.2 Análise CAS Princípio

Veja a definição (retirado da Enciclopédia Baidu):

comparar e de comutação, uma perda de desempenho multissegmentação solução de bloqueio causado por um mecanismo de um processo paralelo, operação CAS inclui três operandos - uma localização de memória (V), espera-se que o valor inicial (A) e o novo valor (B). Se a posição de memória do valor original corresponde ao valor esperado, então o processador irá atualizar automaticamente o valor de localização para o novo valor. Caso contrário, o processador não faz nada. Em ambos os casos, ele retorna o valor da posição antes da instrução CAS. CAS explicou de forma eficaz“我认为位置V应该包含值A;如果包含该值,则将B放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。"

Em seguida, desenhe um diagrama para explicar:
Aqui Insert Picture Descrição


2 CAS possíveis problemas


problema 2.1 ABA

CAS novo para dizer a verdade quando, na verdade, eu acho que o problema ABA. ☺☺☺

1,2 pode saber, no momento da operação requerida valor CAS, verifique o valor não mudou, se não mudou é atualizado, mas se um valor é A, tornou-se um B, ele é um A, em seguida, usar o CAS você vai encontrar o seu valor não mudou, mas na verdade mudar o check - que é chamado do problema ABA>.

Por exemplo ponto popular, você derrama um copo de colocar água sobre a mesa, fez outra coisa, e então você beber um colega devolveu-te um copo de água, você ainda voltar para ver a água, se levantar para beber , não importa se você é meia povo da água beber, apenas água ainda está preocupado, ok, mas se você é um povo que fala mais de higiene, então você certamente perturbar. . .

problema soluções ABA é realmente muito simples, é usar o número da versão. Em frente do número de versão adicional variável, cada vez que o número da versão actualização variável é incrementado por um, então A → B → A torna-se 1A → 2B → 3A acima.


2.2 grandes longos tempos de ciclo gerais

Se o tempo não for bem sucedida CAS rotação, ele vai trazer um grande custo de execução da CPU.


2.3 operação atômica para garantir que apenas uma variável compartilhada

Ao executar operações em uma variável compartilhada, podemos usar a abordagem do ciclo CAS para garantir uma operação atômica, mas 对多个共享变量操作时,循环CAS就无法保证操作的原子性,desta vez podemos 用锁.

Há também uma maneira complicada, é mesclar várias variáveis ​​compartilhadas em uma variável compartilhada para operar. Por exemplo, existem duas variáveis ​​compartilhadas i = 2, j =, uma junção em ij = 2a, e para operar com o CAS ij. Começando a partir de Java 1,5, classes JDK AtomicReference fornecido para garantir o átomo de referência entre objectos pode ser variável, em que a pluralidade de objectos de uma operação CAS é realizada.


3 apoio JDK para o CAS - classe inseguro

java fornece apoio para a operação de CAS, em particular, na classe sun.misc.unsafe, declarar como se segue:

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

Os parâmetros dos significados acima:

  • Parâmetros var1: representa o objeto a ser operado
  • Parâmetros var2: indica o endereço de offset da propriedade do objeto a ser operado
  • Parâmetros var4: um valor que representa uma desejados necessidades de dados a ser modificado
  • Parâmetros var5 / Var6: Para modificar a nova mina representa um valor de

注意:classe inseguro tem a capacidade de tornar a linguagem Java como ponteiros C como operando espaço de memória, mas também traz ponteiro problemas. O uso excessivo de classe inseguro fará a chance de erro se torna grande, e, portanto, não recomenda o uso de oficial Java, quase nenhum documento oficial. objeto inseguro não pode ser chamado diretamente, apenas através de reflexão.


Os 4 classes JDK associado operações atômicas Introdução - mecanismos CAS subjacentes


4.1 AtomicInteger

  • int addAndGet (int delta): valor de entrada exemplo numérico atomicamente (dentro de valor AtomicInteger) são adicionados, e devolve o resultado.
  • boolean compareAndSet (int esperar, atualização int): Se o valor de entrada é igual ao valor esperado atomicamente definir o valor do valor de entrada.
  • int getAndIncrement (): valor atomicamente atual mais 1, nota que este é o valor de retorno antes de incremento.
  • int getAndSet (int newValue): conjunto atomicamente newValue para um valor de, e devolver o valor antigo.

4,2 AtomicIntegerArray

O caminho principal para proporcionar matriz actualização inteiro atómica, que é usado como se segue.

  • int addAndGet (int i, int delta): valores atomicamente de entrada para o elemento de matriz no índice i é adicionado.
  • booleano compareAndSet (int i, int esperar, actualização int): Se o valor da corrente é igual ao valor esperado, os elementos do array atomicamente i é configurado para actualizar os valores de posição.

Note-se que, através da construção de uma matriz de valor passado para o método, em seguida, AtomicIntegerArray irá apresentar uma cópia da matriz, de modo que quando as modificações internas AtomicIntegerArray elemento da matriz não vão afectar a matriz de entrada.


tipos de referência 4.3 de actualização

atualização Atomic tipos básicos de AtomicInteger, só pode actualizar uma variável, se você deseja atualizar múltiplas variáveis ​​atômicas, você precisa usar este tipo de referência classe atualizações atômicas fornecidos. pacote Atómica prevê as seguintes três classes.

  • AtomicReference
    tipo de referência atualização atômica.
  • AtomicStampedReference
    利用版本戳的形式记录了每次改变以后的版本号,这样的话就不会存在ABA问题了。这就是AtomicStampedReference的解决方案。AtomicMarkableReference跟AtomicStampedReference差不多, AtomicStampedReference是使用pair的int stamp作为计数器使用,AtomicMarkableReference的pair使用的是boolean mark。 还是那个水的例子,AtomicStampedReference可能关心的是动过几次,AtomicMarkableReference关心的是有没有被人动过,方法都比较简单。
  • AtomicMarkableReference:
    atômica conjunto atualização marque com um tipo de referência. Atom pode atualizar um booleano tipos de bandeira e de referência. Construtor é AtomicMarkableReference (V initialRef, booleaninitialMark).

4.4 aula de campo atualização atômica

Se a necessidade de atualizar um campo de uma classe de átomos, os átomos precisam de atualização com base em campo utilização, pacote Atómica prevê a seguinte atualização campo três átomos de classes.
Para atualizar atomicamente aula de campo requer duas etapas. O primeiro passo, porque as aulas de campo atualização atômicos são classes abstratas, cada vez usando um método estático usado must newUpdater () para criar um atualizador, ea necessidade de criar classes e atributos que você deseja atualizar. O segundo passo,更新类的字段(属性)必须使用public volatile修饰符。

  • AtomicIntegerFieldUpdater:
    atualização atômica atualizador campo inteiro.
  • AtomicLongFieldUpdater:
    atualização atômica atualizador campo inteiro longo.
  • AtomicReferenceFieldUpdater:
    tipos de referência atualização Atómica no domínio.

Publicado 216 artigos originais · Louvor obteve 284 · vista 490 000 +

Acho que você gosta

Origin blog.csdn.net/nrsc272420199/article/details/105032873
Recomendado
Clasificación