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

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

  • CAS
    • CAS的使用
      • 无锁编程
    • CAS缺陷:ABA问题

)

CAS

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

针对不同的操作系统,JVM 用到了不同的 CAS 实现原理简而言之,是因为硬件予以了支持,软件层面才能做到。
我们假设内存中的原数据v,旧的预期值new,需要修改的新值tmp。
比较 new 与 v 是否相等。(比较)
如果比较相等,将 tmp 写入 v。(交换)
返回操作是否成功。
多线程——关于面试中常见的CAS问题你知道了吗?_第1张图片

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

CAS的使用

无锁编程

不使用锁,而是直接用CAS来保证线程安全
多线程——关于面试中常见的CAS问题你知道了吗?_第2张图片
多线程——关于面试中常见的CAS问题你知道了吗?_第3张图片

//线程不安全,两个线程同时修改一个变量得到的结果不一定是十万
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问题

多线程——关于面试中常见的CAS问题你知道了吗?_第4张图片

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

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

你可能感兴趣的:(多线程,多线程,java,thread,并发编程,编程语言)