CAS

关于并发编程CAS算法和AQS框架的理解

不问归期 提交于 2020-03-26 11:12:50
3 月,跳不动了?>>> 在并发编程中我们最常用到的两块:一种是基于CAS 机制实现的Atomic类操作,一种是基于AQS实现的同步类实现如常用的ReentrantLock/Semaphore/CountDownLatch等; CAS: CAS是英文单词Compare and Swap的缩写,翻译过来就是比较并替换。 CAS机制中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。 更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。 从思想上来说,synchronized属于悲观锁,悲观的认为程序中的并发情况严重,所以严防死守,CAS属于乐观锁,乐观地认为程序中的并发情况不那么严重,所以让线程不断去重试更新。 CAS的缺点: 1) CPU开销过大 在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很到的压力。 2) 不能保证代码块的原子性 CAS机制所保证的知识一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用synchronized了。 3) ABA问题 这是CAS机制最大的问题所在。(可以通过版本号解决) AQS: 它维护了一个volatile int state(代表共享资源

CAS的缺点和问题解决

▼魔方 西西 提交于 2020-03-26 11:07:20
3 月,跳不动了?>>> 在并发编程中CAS的缺点和问题,如ABA问题,自旋锁消耗问题、多变量共享一致性问题 ABA: 问题描述:线程t1将它的值从A变为B,再从B变为A。同时有线程t2要将值从A变为C。但CAS检查的时候会发现没有改变,但是实质上它已经发生了改变 。可能会造成数据的缺失。 解决方法:CAS还是类似于乐观锁,同数据乐观锁的方式给它加一个版本号或者时间戳,如AtomicStampedReference 自旋消耗资源: 问题描述:多个线程争夺同一个资源时,如果自旋一直不成功,将会一直占用CPU。 解决方法:破坏掉for死循环,当超过一定时间或者一定次数时,return退出。JDK8新增的LongAddr,和ConcurrentHashMap类似的方法。当多个线程竞争时,将粒度变小,将一个变量拆分为多个变量,达到多个线程访问多个资源的效果,最后再调用sum把它合起来。 虽然base和cells都是volatile修饰的,但感觉这个sum操作没有加锁,可能sum的结果不是那么精确。 public long sum() { Cell[] as = cells; Cell a; long sum = base; if (as != null) { for (int i = 0; i < as.length; ++i) { if ((a = as[i]) != null) sum

面试必备之乐观锁与悲观锁

醉酒当歌 提交于 2020-03-25 19:09:34
何谓悲观锁与乐观锁 乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。 悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。 乐观锁 总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。 两种锁的使用场景 从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候

面试刷题10:ConcurrentHashMap如何保证线程安全?

让人想犯罪 __ 提交于 2020-03-25 17:43:25
3 月,跳不动了?>>> <br /> <br /> <br />集合框架中的HashTable,Stack,以及同步包装集合在高并发场景下都非常低效,java提供了并发包应对高并发场景。<br /> <br /> <br />我是李福春,我在准备面试,今天的问题是?<br /> <br />java提供了哪些并发的容器?ConcurrentHashMap如何保证线程安全?<br /> <br /> java体系中的并发容器 <br /> <br />java体系中有如下同步容器:<br /> <br />1, HashTable,Stack 同步容器,内部使用sychronized关键字保证同步操作;<br /> <br />2,同步包装器Collections.synchronizedMap(),内部也使用sychronized关键字保证同步操作; 3,并发包提供的同步容器,比如ConcurrentHashMap , CopyOnWriteArrayList , ArrayBlockingQueue,SynchronizedQueue ConcurrentHashMap的同步分析 <br /> <br />为何会出现ConcurrenHashMap?<br /> <br />1, HashTable在高并发场景下性能低下;<br /> <br />2,HashMap

ReetrantLock源码剖析

爷,独闯天下 提交于 2020-03-25 12:20:54
3 月,跳不动了?>>> ReentrantLock源码剖析 ​ 这里又是看了忘忘了看系列之ReetrantLock,今天趁着有时间记录下ReentrantLock源码的学习过程。这篇博客主要记录以下几个方面内容。 欢迎各位多提建议或者意见 ​ 1、ReetrantLock和Sync的继承结构 ​ 2、ReetrantLock构造函数们及AQS的核心属性 ​ 3、ReetrantLock锁的使用示例 ​ 4、ReetrantLock的 原理 及 核心 方法和设计思想 1、ReetrantLock和Sync的继承结构 ​ 上图就是ReetrantLock和Sync的继承结构及关系,ReetrantLock内部有一个成员变量Sync,Sync又继承自AQS(AbstractQueuedSynchronizer)。ReetrantLock内部同时也有两个内部类FairSync和NonfairSync(都是Sync的子类),两个类内部只有两个方法,都是重写了父类的方法,分别是lock()和tryAcquire()。 2、ReetrantLock构造函数们及AQS的核心属性 2.1 先介简单的绍构造函数 // 常用构造函数,内部创建非公平锁 public ReentrantLock() { sync = new NonfairSync(); } // 通过手工指定是公平锁还是非公平锁

深入理解Synchronized

拥有回忆 提交于 2020-03-23 22:13:08
3 月,跳不动了?>>> 目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug Lea。本文并不比较synchronized与Lock孰优孰劣,只是介绍二者的实现原理。 数据同步需要依赖锁,那锁的同步又依赖谁?synchronized给出的答案是在软件层面依赖JVM,而Lock给出的方案是在硬件层面依赖特殊的CPU指令,大家可能会进一步追问:JVM底层又是如何实现synchronized的? 本文所指说的JVM是指Hotspot的6u23版本,下面首先介绍synchronized的实现: synrhronized关键字简洁、清晰、语义明确,因此即使有了Lock接口,使用的还是非常广泛。其应用层的语义是可以把任何一个非null对象作为"锁",当synchronized作用在方法上时,锁住的便是对象实例(this);当作用在静态方法时锁住的便是对象对应的Class实例,因为Class数据存在于永久带,因此静态方法锁相当于该类的一个全局锁;当synchronized作用于某一个对象实例时,锁住的便是对应的代码块。在HotSpot JVM实现中,锁有个专门的名字:对象监视器。 1. 线程状态及状态转换 当多个线程同时请求某个对象监视器时,对象监视器会设置几种状态用来区分请求的线程:

【原创】Java并发编程系列16 | 公平锁与非公平锁

时光毁灭记忆、已成空白 提交于 2020-03-23 21:49:34
3 月,跳不动了?>>>      本文为 何适原创并发编程系列 第 16 篇,文末有本系列文章汇总。   上一篇提到重入锁 ReentrantLock 支持两种锁,公平锁与非公平锁。那么这篇文章就来介绍一下公平锁与非公平锁。   为什么需要公平锁?   ReentrantLock 如何是实现公平锁和非公平锁的?   公平锁和非公平锁又都有什么优缺点呢?   饥饿   我们知道 CPU 会根据不同的调度算法进行线程调度,将时间片分派给线程,那么就可能存在一个问题:某个线程可能一直得不到 CPU 分配的时间片,也就不能执行。    一个线程因为得不到 CPU 运行时间 ,就会处于饥饿状态。如果该线程一直得不到 CPU 运行时间的机会,最终会被“饥饿致死”。   1.1 导致线程饥饿的原因    高优先级线程吞噬所有的低优先级线程的 CPU 时间。   每个线程都有独自的线程优先级,优先级越高的线程获得的 CPU 时间越多,如果并发状态下的线程包括一个低优先级的线程和多个高优先级的线程,那么这个低优先级的线程就有可能因为得不到 CPU 时间而饥饿。    线程被永久堵塞在一个等待进入同步块的状态。   当同步锁被占用,线程处在 BLOCKED 状态等锁。当锁被释放,处在 BLOCKED 状态的线程都会去抢锁,抢到锁的线程可以执行,未抢到锁的线程继续在 BLOCKED 状态阻塞

死磕 java线程系列之自己动手写一个线程池

时间秒杀一切 提交于 2020-03-23 16:48:21
3 月,跳不动了?>>> (手机横屏看源码更方便) 问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写的线程池如何测试? 简介 线程池是Java并发编程中经常使用到的技术,那么自己如何动手写一个线程池呢?本文彤哥将手把手带你写一个可用的线程池。 属性分析 线程池,顾名思义它首先是一个“池”,这个池里面放的是线程,线程是用来执行任务的。 首先 ,线程池中的线程应该是有类别的,有的是核心线程,有的是非核心线程,所以我们需要两个变量标识核心线程数量coreSize和最大线程数量maxSize。 为什么要区分是否为核心线程呢?这是为了控制系统中线程的数量。 当线程池中线程数未达到核心线程数coreSize时,来一个任务加一个线程是可以的,也可以提高任务执行的效率。 当线程池中线程数达到核心线程数后,得控制一下线程的数量,来任务了先进队列,如果任务执行足够快,这些核心线程很快就能把队列中的任务执行完毕,完全没有新增线程的必要。 当队列中任务也满了,这时候光靠核心线程就无法及时处理任务了,所以这时候就需要增加新的线程了,但是线程也不能无限制地增加,所以需要控制其最大线程数量maxSize。 其次 ,我们需要一个任务队列来存放任务,这个队列必须是线程安全的,我们一般使用BlockingQueue阻塞队列来充当,当然使用ConcurrentLinkedQueue也是可以的

CAS Single LogOut(SLO) not working - CAS 4.2.3

ⅰ亾dé卋堺 提交于 2020-03-23 07:56:37
问题 I am having issues with Single LogOut in CAS. I am using CAS server 4.2.3 and Spring 3.2. My client casified applications are configured on spring security. Followed the following documentation, http://docs.spring.io/spring-security/site/docs/3.2.9.RELEASE/reference/htmlsingle/#cas-singlelogout I have 2 cas client web application. When I logout from one of the cas client web application, and refresh the page in the 2nd cas client application which I already logged in (in the same browser in a

利用Python requests库实现cas认证

给你一囗甜甜゛ 提交于 2020-03-23 07:15:39
1.准备工作-背景知识 1.1 requests库简介: python有很多可以用来测试接口的模块,个人觉得,requests库是最好用的, 在Robot Framwork里,它的测试库 requestsLibrary,也是基于requests写的。 1.1.1 安装: 作为第三方模块,使用前,需要安装,最简单的安装方式如下 pip install requests 1.1.2 语法(简明版): 1)如何发送请求 : 发送get请求:requests.get(url, params, headers, cookies, verify, allow_redirects...) 发送post请求: requests.post(url, params, data, headers, cookies, verify, allow_redirects...) *****以上只有url参数是必填的,其他可以根据需要选填 *****除了get和post,还支持其他http请求,比如delete等等,不过在我们的cas认证中,只需要get和post;而且一般的接口测试中,最常用的也就是get和post消息 2)如何得到响应: 假设发送了一个请求: r=requests.get(url, params, headers, cookies, verify, allow_redirects...)