O que é CAS?
Compare e defina
public class CASDemo{
public static void main(String[] args){
AtomicInteger atomicInteger=new AtomicInteger(5);
boolean flag1=atomicInteger.compareAndSet(5,2019);
//result==2019
int result1=atomicInteger.get();
boolean flag2=atomicInteger.compareAndSet(5,2001);
//修改失败,result==2019
int result1=atomicInteger.get();
}
}
atomicInteger.compareAndSet (a, b)
1) O valor anterior é o valor esperado, e o valor da memória física esperada é igual a este valor
2) Se o valor real for igual ao esperado, altere o valor para be grave-o na memória física. Se for diferente, não o escreva.
Princípio básico do CAS
Método getAndAddInte () de classe insegura + pensamento CAS
var1 --- próprio objeto AtomicIntger
var2 --- O endereço de referência do valor do objeto
var4 --- O valor que precisa ser alterado
var5 --- O valor real na memória principal encontrado usando var1 e var2
Use o valor atual do objeto para comparar com var5:
Se for o mesmo, atualize var5 + var4 e retorne verdadeiro
Se eles forem diferentes, continue pegando o valor e compare novamente até que a atualização seja concluída
Aqui estão os motivos para usar CAS em vez de bloqueios sincronizados:
Se bloqueios são usados, a consistência é garantida, mas a simultaneidade é reduzida. O modelo do-while pode ser usado para obter rotação e garantir a simultaneidade
Suponha que dois threads, thread A e thread B, executem a operação getAndAddInt ao mesmo tempo:
1) O valor original do valor no AtomicInteger é 3, ou seja, o valor do AtomicInteger na memória principal é 3. De acordo com o modelo JMM, o encadeamento A e o encadeamento B guardam, cada um, uma cópia do valor 3 para sua respectiva memória de trabalho
2) O thread A obtém o valor 3 por meio de getIntVolatile (var1, var2), então o thread A é suspenso
3) O thread B também obtém o valor 3 por meio do método getIntVolatile . Nesse momento, o thread B não está suspenso e executa o método compareAndSwapInt . O valor da memória de comparação também é 3, e o valor da memória foi modificado com êxito para 4
4) Neste momento, o encadeamento A retoma, executa o método compareAndSwapInt e descobre que o valor número 3 em sua mão é inconsistente com o valor número 4 da memória principal, indicando que o valor foi modificado por outros encadeamentos primeiro, então a modificação do thread A falha desta vez, só consigo lê-lo novamente
5) O thread A readquire o valor do valor, porque o valor da variável é modificado por volatile, então outros threads o modificam, o thread A sempre pode ver, o thread A continua a executar compareAndSwapInt para comparação e substituição até ter sucesso
Resumindo
CASO:
Compare o valor na memória de trabalho atual com o valor na memória principal, se eles forem iguais, execute a operação especificada, caso contrário, continue a comparar até que os valores na memória principal e na memória de trabalho sejam consistentes
Aplicação CAS:
O CAS tem 3 operandos a serem modificados o valor de memória V, o antigo valor esperado A e o valor atualizado B. Se e somente se o valor esperado A e o valor de memória V forem iguais, modifique a memória V para B, caso contrário as instruções não serão realizadas. Repita o processo acima até ter sucesso
Desvantagens do CAS:
1) Longo tempo de ciclo e alta sobrecarga (do-while)
2) Garantir apenas o funcionamento atômico de uma variável compartilhada
3) Traga o problema ABA (consulte a postagem do blog https://blog.csdn.net/di_ko/article/details/115066900 )