iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >怎么从JUC源码看CAS
  • 722
分享到

怎么从JUC源码看CAS

2024-04-02 19:04:59 722人浏览 安东尼
摘要

本篇内容主要讲解“怎么从JUC源码看CAS”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么从JUC源码看CAS”吧!1.什么是CAS?说到CAS,基本上都会想

本篇内容主要讲解“怎么从JUC源码看CAS”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么从JUC源码看CAS”吧!

1.什么是CAS?

说到CAS,基本上都会想到乐观、AtomicInteger、Unsafe ...

当然也有可能啥也没想到!

不管你们怎么想, 我第一印象是乐观锁,毕竟做交易更新交易状态经常用到乐观锁,就自然想到这个sql

update trans_order  set order_status = 1  where order_no = 'xxxxxxxxxxx' and order_status = 0;

其实就是 set和where里面都携带order_status。

那什么是CAS?

CAS就是Compare-and-Swap,即比较并替换,在并发算法时常用,并且在JUC(java.util.concurrent)包下很多类都使用了CAS。

非常常见的问题就是多线程操作i++问题。一般解决办法就是添加 synchronized 关键字修饰,当然也可以使用 AtomicInteger  代码举例如下:

public class CasTest {      private static final CountDownLatch LATCH = new CountDownLatch(10);      private static int NUM_I = 0;     private static volatile int NUM_J = 0;     private static final AtomicInteger NUM_K = new AtomicInteger(0);      public static void main(String[] args) throws InterruptedException {          ExecutorService threadPool = Executors.newFixedThreadPool(10);         for (int i = 0; i < 10; i++) {              threadPool.execute(new Runnable() {                 public void run() {                     for (int j = 0; j < 10000; j++) {                         NUM_I++;                         NUM_J++;                         NUM_K.incrementAndGet();                     }                     LATCH.countDown();                 }             });         }         LATCH.await();          System.out.println("NUM_I = " + NUM_I);         System.out.println("NUM_J = " + NUM_J);         System.out.println("NUM_K = " + NUM_K.get());         threadPool.shutdown();     }  }

下面就从AtomicInteger开始了解CAS。

2.源码分析

public class AtomicInteger extends Number implements java.io.Serializable {     private static final long serialVersionUID = 6214790243416807050L;      // setup to use Unsafe.compareAndSwapint for updates     private static final Unsafe unsafe = Unsafe.getUnsafe();     private static final long valueOffset;      static {         try {             valueOffset = unsafe.objectFieldOffset                 (AtomicInteger.class.getDeclaredField("value"));         } catch (Exception ex) { throw new Error(ex); }     }      private volatile int value;      public final int incrementAndGet() {         return unsafe.getAndAddInt(this, valueOffset, 1) + 1;     }     public final int decrementAndGet() {         return unsafe.getAndAddInt(this, valueOffset, -1) - 1;     }  }

可以看出里面使用了Unsafe类下的getAndAddInt方法,Unsafe类很多方法是本地(native)方法,主要是硬件级别的原子操作。

 public final int getAndAddInt(Object var1, long var2, int var4) {     int var5;     do {         // 获取在var1在内存的值         var5 = this.getIntVolatile(var1, var2);         // 将var1赋值为var5+var4, 赋值时会判断var1是否为var5     } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));      return var5; } // 原子操作 public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

至于 compareAndSwapInt 的分析就忽略了。

看完代码过程其实就是:

  •  比较var1的值是否为var4,是的话将var1更新为var5。

  • 如果不是的话就一直循环,直到var1是var4。

3.问题总结

怎么从JUC源码看CAS

  • 这要是一直获取不到,岂不是一直循环。线程多的情况下,会自旋很长时间,导致浪费资源。

  • 你更新了,  我又给你更新回去了,你也不知道。ABA问题!比如像这样,A想更新值为a,还未抢到资源,这时候B进行了更新,将对象更新为了b,然后又马上更新回了a,  这时候A是什么都不知道的。

以乐观锁举例:

-- 0 -> 1 update trans_order  set order_status = 1  where order_no = 'xxxxxxxxxxx' and order_status = 0;  -- 1 -> 0 update trans_order  set order_status = 1  where order_no = 'xxxxxxxxxxx' and order_status = 0;  -- 0 -> 1 update trans_order  set order_status = 1  where order_no = 'xxxxxxxxxxx' and order_status = 0;

解决办法可以添加version进行版本号控制。

-- 0 -> 1 update trans_order  set order_status = 1  where order_no = 'xxxxxxxxxxx' and order_status = 0 and version = 0;  -- 1 -> 0 update trans_order  set order_status = 1  where order_no = 'xxxxxxxxxxx' and order_status = 0 and version = 1;  -- 0 -> 1 update trans_order  set order_status = 1  where order_no = 'xxxxxxxxxxx' and order_status = 0 and version = 0;

代码中可以看 AtomicStampedReference 类:

 public boolean compareAndSet(V   expectedReference,                              V   newReference,                              int expectedStamp,                              int newStamp) {     Pair<V> current = pair;     return         expectedReference == current.reference &&         expectedStamp == current.stamp &&         ((newReference == current.reference &&             newStamp == current.stamp) ||             casPair(current, Pair.of(newReference, newStamp))); }

其实就是额外增加一个标志(stamp)来防止ABA的问题, 类似乐观锁的version。

到此,相信大家对“怎么从JUC源码看CAS”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: 怎么从JUC源码看CAS

本文链接: https://www.lsjlt.com/news/84676.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么从JUC源码看CAS
    本篇内容主要讲解“怎么从JUC源码看CAS”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么从JUC源码看CAS”吧!1.什么是CAS说到CAS,基本上都会想到...
    99+
    2022-10-19
  • 怎么从Chrome源码看浏览器进行layout布局
    本篇文章为大家展示了怎么从Chrome源码看浏览器进行layout布局,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。假设有以下html/css:<div&nb...
    99+
    2022-10-19
  • 怎么从Linux源码看Socket TCP的Listen及连接队列
    怎么从Linux源码看Socket TCP的Listen及连接队列,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。从Linux源码看Socket(TCP)的lis...
    99+
    2023-06-15
  • Java怎么看Lambda源码
    本文小编为大家详细介绍“Java怎么看Lambda源码”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java怎么看Lambda源码”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1、Demo首先我们来看一个 La...
    99+
    2023-06-30
  • 详解从Linux源码看Socket(TCP)的bind
    目录一、一个最简单的Server端例子二、bind系统调用2.1、inet_bind2.2、inet_csk_get_port三、判断端口号是否冲突四、SO_REUSEADDR和SO_REUSEPORT五、SO_RE...
    99+
    2022-06-03
    Linux 源码 Socket bind
  • 如何从设计模式看OkHttp源码
    今天就跟大家聊聊有关如何从设计模式看OkHttp源码,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。使用读源码,首先就要从它的使用方法开始:val&n...
    99+
    2022-10-19
  • 从MySQL源码看其网络IO模型
    从MySQL源码看其网络IO模型 前言 MySQL是当今最流行的开源数据库,阅读其源码是一件大有裨益的事情(虽然其代码感觉比较凌乱)。而笔者阅读一个Server源码的习惯就是先从其网络IO模型看起。于是,便有了本篇博客。 MySQL启动So...
    99+
    2017-06-01
    从MySQL源码看其网络IO模型 数据库入门 数据库基础教程 数据库 mysql
  • Java从源码看异步任务计算FutureTask
    目录了解一下什么是FutureTask?FutureTask 是如何实现的呢?FutureTask 运行流程FutureTask 的使用前言: 大家是否熟悉FutureTask呢?或...
    99+
    2022-11-13
  • HTML怎么查看源代码
    小编给大家分享一下HTML怎么查看源代码,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!     HTML标...
    99+
    2022-10-19
  • 分析从Linux源码看TIME_WAIT的持续时间
    目录一、前言二、首先介绍下Linux环境三、TIME_WAIT状态转移图四、持续时间真如TCP_TIMEWAIT_LEN所定义么?五、TIME_WAIT定时器源码5.1、inet_twsk_schedule5...
    99+
    2022-06-03
    Linux TIME_WAIT
  • idea怎么查看注解源码
    您可以使用下列步骤来查看idea中注解的源码: 首先,在您的项目中找到包含注解的类或方法。 将光标放置在注解上,并按下Ctrl键(...
    99+
    2023-10-26
    idea
  • 怎么看python函数源代码
    在python中使用inspect.getsource函数查看函数源代码,具体方法如下:import inspectdef print_hh():print('hh')source = inspect.getsource(print_hh)...
    99+
    2022-10-09
  • java怎么查看注解源码
    要查看Java注解的源码,可以按照以下步骤进行: 打开Java IDE(例如Eclipse、IntelliJ IDEA)。 在项目...
    99+
    2023-10-26
    java
  • plsql怎么查看sql源码语句
    在PL/SQL中,您可以使用以下方法来查看SQL源码语句:1. 使用DBMS_OUTPUT.PUT_LINE函数:您可以在PL/SQ...
    99+
    2023-10-11
    plsql sql
  • 怎样理解从Vue.js源码看异步更新DOM策略及nextTick
    怎样理解从Vue.js源码看异步更新DOM策略及nextTick,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。操作DOM在使用vue.js...
    99+
    2022-10-19
  • POSTGRESQL10.8怎么用源码安装主从搭建
    本篇内容介绍了“POSTGRESQL10.8怎么用源码安装主从搭建”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有...
    99+
    2022-10-18
  • 从面试角度怎么分析LinkedList源码
    本篇内容介绍了“从面试角度怎么分析LinkedList源码”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!注...
    99+
    2022-10-19
  • gitee怎么看别人的开源代码
    Gitee是一家国内知名的代码托管平台,其受到广大开发者的喜爱和青睐。在Gitee上,用户可以分享自己的开源代码,也能够查看和学习其他人的优秀代码,进一步提升自己的编码能力。本文将介绍如何在Gitee上查看别人的开源代码。第一步:打开Git...
    99+
    2023-10-22
  • 阿里云服务器怎么看源码
    要查看阿里云服务器的源码,可以按照以下步骤进行操作: 首先,你需要安装阿里云服务器的相关软件和驱动,这些软件和驱动需要通过阿里云官网或者阿里云商店来下载安装。 安装完软件后,你需要进入到阿里云服务器的网站,在网站页面上找到服务器的管理界...
    99+
    2023-10-27
    阿里 怎么看 源码
  • 从Linux源码看Socket(TCP)Client端的Connect的示例详解
    前言 笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情。 今天笔者就来从Linux源码的角度看下Client端的Socket在进行Connect的时候到底做了哪些事情。由于篇幅...
    99+
    2022-06-03
    Linux源码看Socket linux Client端的Connect
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作