6.23Java多线程CAS原子操作

6.23Java多线程CAS原子操作

锁的分类

  • 悲观锁:

    • synchronized是独占锁(悲观锁)

    • 其特点是

      • 会导致其他所有需要锁的线程挂起,等待持有锁的线程释放资源

  • 乐观锁(Compare and Swap:比较与交换)

    • 每次操作不加锁,假设没有冲去取完成某项操作

      • 如果因为冲突导致失败则会重试到成功为止

    • 乐观锁的实现--->这个思想就是CAS思想

      • 方法:

        • 三个值:

          • 当前内存值V

          • 旧的预期值A

          • 将更新的值B

        • 先获取到内存中当前的内存之V

        • 将V与A比较

        • 如果V和A相等,将B赋值给V并且返回true

        • 否则什么都不做返回false

          • if(V == A){
               V = B;
               return true;
            }else {
               return false;
            }
        • 特点:

          • CAS是一组原子操作,不会被外部打断

          • 属于硬件级别的操作(利用CPU的CAS指令,借助JNI来完成的非阻塞算法),效率比加锁操作高

        • ABA问题:

          • 如果变量V初次读取的时候是A,准备赋值的时候检查也是A能否说明它没有被其他线程修改过?

          • 如果这段期间曾经被改成B然后又改回A那么CAS操作会误认为它从来没有被修改过

          • 通过日志查看操作来确定没有被动过--->C或C++实现原理

  • 按照可沿用属性分类:

    • 可重入锁

      • 公平锁

      • 不公平锁

      (根据是否按照队列顺序进行操作来划分)

    • 不可重入锁

  • 自旋锁

操作核心

两大核心值:

version--->1--->被更新以后的版本变为2

number-->10--->9更新的时候比较版本是否相同,版本相同更新,版本不同不更新。

比较并交换数据

CAS原子性操作--->利用Java当中自带的类实现
package thread.rearrangement;

import java.util.concurrent.atomic.AtomicInteger;

/**
* CAS比较并交换
* @since JDk 1.8
* @date 2021/6/23
* @author Lucifer
*/
public class CAS {

   /*先加入资源类对象*/
   //库存对象
   private static AtomicInteger stock = new AtomicInteger(5);
   /*
   Atomic原子性操作里面都会用到原子性的思想
   里面用的不是synchronized同步锁
   而是用CAS的思想,效率高,是硬件级别的操作
    */

   public static void main(String[] args) {

       /*利用lambda表达式开辟五个线程*/
       for (int i=0; i<5; i++){
           new Thread(() -> {

               /*模拟延时*/
               try {
                   Thread.sleep(1000);
              }catch (InterruptedException e){
                   System.out.println(e.getMessage());
                   e.printStackTrace();
              }

               /*抢购库存的数据,就是减少数据*/
               Integer left = stock.decrementAndGet();
               /*
               这个方法的源码当中就存在CAS的思想
               */

               /*判断*/
               if (left<1){
                   System.out.println("抢完了...");
                   return;
              }

               /*打印出获取到资源的线程*/
               System.out.println(Thread.currentThread().getName() + "抢了一件商品");
               System.out.println("还剩" + left);

          }).start();
      }
  }

}

 

posted @ 2021-06-23 15:53  俊king  阅读(128)  评论(0编辑  收藏  举报