https://blog.csdn.net/qq_40297844/article/details/106437993
CAS (Compare And Swap),即比较并交换,是解决多线程并行情况下使用锁造成性能损耗的一种机制。在 JAVA 中,sun.misc.Unsafe 类提供了硬件级别的原子操作来实现 CAS。 java.util.concurrent 包下的大量类 (AtomicInteger, AtomicBoolean, AtomicLong, … )都使用了这个 Unsafe.java 类的 CAS 操作。至于 Unsafe.java 的具体实现这里就不讨论了。 CAS 本身是一种乐观锁的实现方式,在 Java 中的运用很多:
在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁
本文主要讲在Java并发编程的时候,如果保证变量的原子性,在JDK提供的类中是怎么保证变量原子性的呢?。对应Java中的包是:java.util.concurrent.atomic包下。因为涉及到了CAS算法,需要对CAS算法讲解及CAS算法三个问题怎么解决以及和Synchroized比较。文章比较长,所以就分为上下两个篇幅讲解。本文是上篇《Java并发之原子变量及CAS算法-下篇》
1. 从官网下载CAS Client, 将客户端的jar, cas-client-core-3.2.1.jar commons-logging-1.1.jar 引入到web应用程序的classpath中
这个对接也就是自己的spring Session体系的系统作为一个cas client主体,然后再去对接CAS
文章定期同步到github:https://github.com/Bronya0/JavaBook
悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。再比如Java里面的同步原语synchronized关键字的实现也是悲观锁。
大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说java 悲观锁[Java怎样解决高并发],希望能够帮助大家进步!!!
1. CAS机制 CAS定义 CAS全称为Compare-and-swap,是属于并发多线程中实现同步原子操作的指令,是依赖于硬件层次的原语发起的原子操作 从程序代码理解上,CAS包含check then act的两个动作,这两个动作在在硬件的处理器上是具备原子性,也就是在操作系统底层上已经实现对CAS算法的原子性保证 CAS 使用条件 需要输入两个数值,一个是期望修改前的值(旧值),一个是需要被设置的新值(新值) 进行CAS操作需要进行对预期值的check操作 CAS之简易版本 通过CAS设置新值 //
顾名思义,就是很悲观,假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁。
Shiro 1.2开始提供了Jasig CAS单点登录的支持,单点登录主要用于多系统集成,即在多个系统中,用户只需要到一个中央服务器登录一次即可访问这些系统中的任何一个,无须多次登录。此处我们使用Jasig CAS v4.0.0-RC3版本:
锁的一种宏观分类方式是悲观锁和乐观锁。悲观锁与乐观锁并不是特指某个锁(Java 中没有哪个 Lock 实现类就叫 PessimisticLock 或 OptimisticLock),而是在并发情况下的两种不同策略。
CAS加volatile关键字是实现并发包的基石。没有CAS就不会有并发包,synchronized是一种独占锁、悲观锁,java.util.concurrent中借助了CAS指令实现了一种区别于synchronized的一种乐观锁。
在高并发的业务场景下,线程安全问题是必须考虑的,在JDK5之前,可以通过synchronized或Lock来保证同步,从而达到线程安全的目的。但synchronized或Lock方案属于互斥锁的方案,比较重量级,加锁、释放锁都会引起性能损耗问题。
CAS的全称为Compare-And-Swap ,它是一条CPU并发原语。它的功能是判断内存某个位置的值是否为预期值,如果是则更新为新的值,这个过程是原子的。
近期看一些源码,会有一些注释是LockFree。这到底啥玩意儿?之前我也不知道啊,遂赶紧上网查之,总结了一些东西作为记录,与大家分享。
在Java中,J实现原子操作 可以通过锁和循环CAS的方式来实现原子操作。 1 使用循环CAS操作原子操作 package com.yy;
技术是为了解决问题而生的,通过 CAS 我们可以以无锁的方式,保证对共享数据进行 “读取 - 修改 - 写回” 操作序列的正确性。
传统的并发控制手段,如使用synchronized关键字或者ReentrantLock等互斥锁机制,虽然能够有效防止资源的竞争冲突,但也可能带来额外的性能开销,如上下文切换、锁竞争导致的线程阻塞等。而此时就出现了一种乐观锁的策略,以其非阻塞、轻量级的特点,在某些场合下能更好地提升并发性能,其中最为关键的技术便是Compare And Swap(简称CAS)。
本文主要讲在Java并发编程的时候,如果保证变量的原子性,在JDK提供的类中式怎么保证变量原子性的呢?。对应Java中的包是:java.util.concurrent.atomic包下
当我们研究AQS框架时(对于AQS不太熟知可以先阅读《什么是JDK内置并发框架AQS》,会发现AbstractQueuedSynchronizer这个类很多地方都使用了CAS操作。在并发实现中CAS操作必须具备原子性,而且是硬件级别的原子性。我们知道Java被隔离在硬件之上,硬件级别的操作明显力不从心。这时为了能够执行操作系统层面的操作,就必须要通过用C++编写的native本地方法来扩展实现。一般可以通过JNI方式实现Java代码调用C++代码
CAS的全称为Compare-And-Swap,它是一条CPU并发原语。它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的。CAS并发原语体现在JAVA语言中就是 sun.misc.Unsafe类中的各个方法。调用UnSafe类中的CAS方法,JVM会帮我们实现出CAS汇编指令。这是一种完全依赖于硬件的功能。那么为什么CAS会出现呢?它的作用是怎样的? 实现并发的传统方式是加锁,JAVA中的锁有synchronized和Lock。Lock是基于AQS和CAS实现的,在此先不叙述。对于synchronized锁,JVM在执行它的时候会依赖操作系统的临界区机制。这样的话,每次执行到synchronized锁,都会经历用户态和内核态之间的切换。这个过程的消耗是很大的。而且,大多数时候synchronized锁住的操作是很细粒度的。为了细粒度的操作去经历用户态和内核态之间的切换是低效的做法。 说到这,我想到了线程池。大家知道,当线程创建和销毁的时间大于任务执行的时间时,就需要考虑使用线程池了。但如果和任务执行时间相比,线程创建和销毁的时间很少,那么线程池也可不用。 在synchronized中就是这个问题,当需要同步的操作粒度很细时,使用synchronized是不高效的,这时就有CAS存在的意义了。比如对于i++这种并发计数功能,使用synchronized就大材小用了,而使用CAS来实现就会更加的轻量级,性能更好。因此可以看到java.util.concurrent.atomic包中有类似AtomicInteger这种类。我们来看下AtomicInteger类的核心源码:
在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有独占锁. 我们在系列java并发线程实战(1)线程安全和机制原理,已经提到例子,
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。
乐观锁顾名思义就是在操作时很乐观,认为操作不会产生并发问题(不会有其他线程对数据进行修改),因此不会上锁。但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS(compare and swap)算法实现。 简单理解:这里的数据,别想太多,你尽管用,出问题了算我怂,即操作失败后事务回滚、提示。版本号、CAS这2种方法本质上是一样的:假如满足条件,做你想做的事,条件判断是原子的或者是快速的,耗时几乎不计。
我们知道,原子(atom)指化学反应不可再分的基本微粒。在 Java 多线程编程中,所谓原子操作,就是即使命令涉及多个操作,这些操作依次执行,不会被别的线程插队打断。
CAS即Compare And Swap的缩写,翻译成中文就是比较并交换,其作用是让CPU比较内存中某个值是否和预期的值相同,如果相同则将这个值更新为新值,不相同则不做更新,也就是CAS是原子性的操作(读和写两者同时具有原子性),其实现方式是通过借助C/C++调用CPU指令完成的,所以效率很高。CAS的原理很简单,这里使用一段Java代码来描述
锁会导致性能降低,在特定情况可用硬件同步原语替代锁,保证和锁一样数据安全,同时提供更好性能。
官方提供了手脚架工具,可以自定去定义自己的项目,但里面用到了一个query的cdn需要访问国外网站
jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是是悲观锁。
CAS的全称为Compare And Swap,直译就是比较交换。是一条CPU的原子指令,其作用是让CPU先进行比较两个值是否相等,然后原子地更新某个位置的值,其实现方式是基于硬件平台的汇编指令,在intel的CPU中,使用的是cmpxchg指令,就是说CAS是靠硬件实现的,从而在硬件层面提升效率。
由于 Java 的 CAS 同时具有 volatile 读和 volatile 写的内存语义,因此 Java 线程之间的通信现在有了下面四种方式:
Apereo CAS,是CAS协议official reference implementation,也差不多是当前开源的SSO解决方案最好、最成熟的一个了。 当前版本是6.5,https://github.com/apereo/cas-overlay-template/tree/6.5。
CAS乐观锁(原子操作)
在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁 锁机制存在以下问题: 在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。 一个线程持有锁会导致其它所有需要此锁的线程挂起。 如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。 volatile是不错的机制,但是volatile不能保证原子性。因此对于同步最终还是要回到锁机制上来。 独占锁是一种悲观锁,synchronized就是一种独占锁,会导致其它所有需要锁
无锁的Compare and Swap(CAS)操作是一种高效的并发编程技术,通过原子性的比较和交换操作,实现了无锁的线程同步。在我之前的文章《简单理解CAS》
并发编程,为了保证数据的安全,需要满足三个特性:原子性、可见性、有序性。Java 中可以通过锁和 CAS 的方式来实现原子操作。
在并发编程中,CAS算法和原子变量是实现并发控制的关键技术之一。本文将详细介绍CAS算法和原子变量的原理、使用方法和注意事项,包括它们的优点、缺点和适用范围。同时,本文还将利用代码案例介绍如何使用CAS算法和原子变量来解决并发问题。
在面试题(四)中,我们对Synchronized应该有所印象了,它最大的特征就是在同一时刻只有一个线程能够获得对象的监视器(monitor),从而进入到同步代码块或者同步方法之中,即表现为互斥性(排它性)。
简单讲一下这个类。Java 无法直接访问底层操作系统,而是通过本地(native)方法来访问。不过尽管如此,JVM 还是开了一个后门,JDK 中有一个类 Unsafe,它提供了硬件级别的原子操作。
CAS (compare and swap) 是并发算法设计时使用的一种技术。基本上,CAS是将变量的值与期望值进行比较,如果值相等,则将变量的值交换设置为新值。CAS可能听起来有点复杂,但一旦你理解它实际上相当简单,所以让我进一步详细说明这个主题。
我们知道在Java多线程里面关于共享变量的操作,一定是要使用线程同步来保证线程安全的,一旦涉及线程同步,就需要加锁,一旦加锁就意味着某一个时候只能有一个线程在操作,其他的线程如果没有得到锁就会阻塞起来,此时的线程的状态是BLOCKED,当前面的线程释放锁的时候,系统会自动调度当前的线程进入临界区,这里面存在一个问题,就是线程的上下文切换的问题,虽然比起来进程的上下文切换,线程的上下文切换更轻量级,但仍然也是有一定开销的,比如最简单的i++的例子,那么如何有没有一种不需要加锁也能保证线程安全的数据结构呢?答案是肯定的,这就是今天需要谈到的CAS(Compare And Swap或 Compare And Set)。
CAS的全称是compare and swap,它是java同步类的基础,java.util.concurrent中的同步类基本上都是使用CAS来实现其原子性的。
领取专属 10元无门槛券
手把手带您无忧上云