【面试:并发篇32:cas】原子类型

【面试:并发篇32:cas】原子类型

00.前言

如果有任何问题请指出,感谢。

01.解释

JUC提供了一些实现了cas的工具类:三大类 原子整数 原子引用 原子数组

02.原子整数

有AtomicBoolean、AtomicInteger、AtomicLong,这里我们拿AtomicInteger举例

        AtomicInteger i = new AtomicInteger(5);

        System.out.println(i.incrementAndGet()); // ++i
        System.out.println(i.getAndIncrement()); // i++

        System.out.println(i.decrementAndGet()); // --i
        System.out.println(i.getAndDecrement()); // i--

        System.out.println(i.getAndAdd(5)); // 先打印再自增5
        System.out.println(i.addAndGet(5)); // 先自增5再打印

	    i.updateAndGet(value -> value * 10);
	    // 内部是函数式接口 可以使用lambda表达式
	    // 可以自定义运算方式,更新但没有返回值
	    i.getAndUpdate(value -> value * 10);
	    // 返回更新后的返回值

上述都是AtomicInteger类常用的方法 方法对应的操作都是原子的 不会出现线程安全问题 注释中有对应的操作。

03.原子引用

补充

在学下面内容之前,我们要明确一个概念,cas操作中的比较的是地址值或者地址的内容?答案是地址值,下面的ABA问题会体现。

为什么要有原子引用类型

我们知道类型分为基本类型(int long char等)和引用类型(类对象),上述我们的原子整数对应的就是基本类型的cas实现,现在的原子引用就是引用类型的cas实现。

AtomicReference< Object>

介绍
泛型里放要使用的引用类型 保证它的原子性
例子
还是上一篇文章的取钱例子,只不过把int类型换为了BigDecimal类型,我们现在是否还会出现线程安全问题
代码

@Slf4j(topic = "c.Test35")
public class Test35 {
   
    public static void main(String[] args) {
   
        DecimalAccount.demo(new DecimalAccountCas(new BigDecimal("10000")));
    }
}

class DecimalAccountCas implements DecimalAccount {
   
    private AtomicReference<BigDecimal> balance;

    public DecimalAccountCas(BigDecimal balance) {
   
//        this.balance = balance;
        this.balance = new AtomicReference<>(balance);
    }

    @Override
    public BigDecimal getBalance() {
   
        return balance.get();
    }

    @Override
    public void withdraw(BigDecimal amount) {
   
        while(true) {
   
            BigDecimal prev = balance.get();
            BigDecimal next = prev.subtract(amount);
            if (balance.compareAndSet(prev, next)) {
   
                break;
            }
        }
    }
}

interface DecimalAccount {
   
    // 获取余额
    BigDecimal getBalance();

    // 取款
    void withdraw(BigDecimal amount);

    /**
     * 方法内会启动 1000 个线程,每个线程做 -10 元 的操作
     * 如果初始余额为 10000 那么正确的结果应当是 0
     */
    static void demo(DecimalAccount account) {
   
        List<Thread> ts = new ArrayList<>();
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

m0_71229547

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

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

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

打赏作者

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

抵扣说明:

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

余额充值