多线程——关于面试中常见的CAS问题你知道了吗?

关于面试中常见的CAS问题你知道了吗?


)

CAS

CAS的全称是 compare and swap(字面意思就是比较交换) 他是基于硬件提供的一种基础指令, 也是基于这样的指令, 就可以实现一些特殊的功能(实现锁)

针对不同的操作系统,JVM 用到了不同的 CAS 实现原理简而言之,是因为硬件予以了支持,软件层面才能做到。
我们假设内存中的原数据v,旧的预期值new,需要修改的新值tmp。
比较 new 与 v 是否相等。(比较)
如果比较相等,将 tmp 写入 v。(交换)
返回操作是否成功。
在这里插入图片描述

可见当多个线程同时对某个资源进行CAS操作,只能有一个线程操作成功,但是并不会阻塞其他线程,其他线程只会收到操作失败的信号。可见 CAS 其实是一个乐观锁。

CAS的使用

无锁编程

不使用锁,而是直接用CAS来保证线程安全
在这里插入图片描述
在这里插入图片描述

//线程不安全,两个线程同时修改一个变量得到的结果不一定是十万
public class Demo2 {
    private static int num = 0;

    public static void main(String[] args) throws InterruptedException {

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 50000 ; i++) {
                    num++;
                }
            }
        };

        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println(num);

    }
}

每次的结果不同

加锁之后:


public class Demo2 {
    private static int num = 0;

    public static void main(String[] args) throws InterruptedException {

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 50000 ; i++) {
                   synchronized (Demo2.class){
                       num++;

                   }
                }
            }
        };

        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println(num);

    }
}

100000

不加锁使用原子类

import java.util.concurrent.atomic.AtomicInteger;

public class Demo2 {
   // private static int num = 0;

    private static AtomicInteger num = new AtomicInteger(0);
    public static void main(String[] args) throws InterruptedException {

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 50000 ; i++) {
                   synchronized (Demo2.class){
                       num.getAndIncrement();//num++
                       //num.incrementAndGet();//++num

                   }
                }
            }
        };

        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println(num);

    }
}

CAS缺陷:ABA问题

在这里插入图片描述

这个问题就是加入现在有个size为0 有一个线程把他修改为1, 然后紧接着又有一个线程把他修改为0了 那此时仅仅通过CAS的比较是无法区分的

解决这个问题就需要引入额外的信息 (给变量加一个版本号 每次进行修改 都递增版本号)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值