深入理解CAS

本文介绍了Java并发编程中的CAS(Compare and Swap)机制,包括其工作原理、优缺点以及可能导致的ABA问题。通过示例展示了AtomicInteger如何使用CAS实现乐观锁。接着,为了解决ABA问题,文章引入了AtomicStampedReference,通过版本号来确保对象引用的线程安全性。最后,讨论了在使用包装类如Integer时需要注意的对象引用问题。
摘要由CSDN通过智能技术生成

1.什么是CAS?

CAS:比较当前工作内存中的值和主内存的值,如果这个值是期望的,那么则执行操作!,如果不是就一直循环。

缺点:
	1.循环会耗时
	2.一次性只能保证一个共享变量的原子性
	3.ABA问题

CAS 是CPU的并发原语。
在这里插入图片描述
在这里插入图片描述

Unsafe类

2.ABA问题 (乐观锁)(狸猫换太子)AtomicInteger

在这里插入图片描述

	//CAS		compareAndSet比价并交换
	public static void main(String[] args) {
		//原子类
		AtomicInteger atomicInteger = new AtomicInteger(2020);
		
		//如果期望的值达到了,就更新,否则,就不更新
		//CAS 是CPU的并发原语。
		
		//对于我们平时写的SQL: 乐观锁
		//============捣乱的线程===============
		System.out.println(atomicInteger.compareAndSet(2020, 2021));
		System.out.println(atomicInteger.get());
		
		System.out.println(atomicInteger.compareAndSet(2021, 2020));
		System.out.println(atomicInteger.get());
		
		//============期望的线程===============
		System.out.println(atomicInteger.compareAndSet(2020, 2021));
		System.out.println(atomicInteger.get());
	}

在这里插入图片描述

3.原子引用 解决ABA问题(乐观锁) AtomicStampedReference

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

public class CASTest {
	
	//Integer的缓存是 -128 到- 127 也就是说 超过这个范围会创建新的地址  ,地址不一样时,必然!= ,或者使用equals
	//原子应用类,可以保证你在修改对象引用时的线程安全性,比较时可以按照偏移量进行
	static AtomicStampedReference<Integer> atomicInteger = new AtomicStampedReference<>(1, 1);

	//CAS		compareAndSet比价并交换
	public static void main(String[] args) {
		//原子类
		//AtomicInteger atomicInteger = new AtomicInteger(2020);
		
		//1.期望值  	2.版本号
		
		new Thread(()->{
			int i = atomicInteger.getStamp(); //版本号
			System.out.println(Thread.currentThread().getName() + i );
		
			//进行一个修改 改变期望 ,并且3.是版本号 4.是改变后的版本号
			atomicInteger.compareAndSet(1, 2, i, i+1);
			System.out.println(Thread.currentThread().getName() + atomicInteger.getStamp() );
			
			atomicInteger.compareAndSet(2, 1, i, i+1);
			System.out.println(Thread.currentThread().getName() + atomicInteger.getStamp() );
		},"A").start();
		

		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		new Thread(()->{
			int i = atomicInteger.getStamp(); //版本号
			System.out.println(Thread.currentThread().getName() + i );
		
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			atomicInteger.compareAndSet(1, 5 , i, i+1);
			System.out.println(Thread.currentThread().getName() + atomicInteger.getStamp() );
		},"B").start();
		
	}
}

在这里插入图片描述

如果泛型是包装类,注意对象引用问题

Integer的缓存是 -128 到- 127 也就是说 超过这个范围会创建新的地址 ,地址不一样时,必然!= ,或者使用equals

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只小小狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值