CAS

java学习记录---CAS乐观锁

最后都变了- 提交于 2020-02-27 22:48:52
CAS,全称 Compare And Swap (比较与交换),是一种乐观锁,同样是锁相比 synchronized 性能却要高不少,因为是 synchronized 阻塞的,而CAS是非阻塞的。CAS主要有3个操作数,内存值V,预期的旧值A,需要修改的新值B,可以这样理解:在V的地址把A改成B,当V位置的值与预期的旧值A相同时候,则修改成B,否则不更新。 下面看个图简单理解一下CAS:当线程1和线程2同时操作内存V,线程1想要把内存V的变量值从A(2)改成B(1)而线程2想要把V的变量值从A(2)改成B(3)。假设这个时候是线程1优先抢到资源所以线程1先进行CAS操作,这个时候预期旧值2是相等的则执行了更新,更新完后内存V的变量值就变成1,这个时候线程2才进入比较预期的A值与V中实际的变量值已经不相同了,所以更新失败。 这个图看上去是 Compare And Swap 是同时操作,但实际上是分2部执行:1.比较(compare),2.交换(swap),它的原子性是通过硬件实现的,而不是我们java代码实现 java提供的CAS操作类 我们随便找其中一个Atomic类学习 当V的值与A相等则更新成功 public static void main(String[] args) { // 定义 Integer 的 CAS 类 AtomicInteger AI = new

AQS (AbstractQueuedSynchronizer)源码导读:锁的获得与释放

早过忘川 提交于 2020-02-27 18:57:50
AQS是什么? AbstractQueuedSynchronizer简称AQS是一个抽象同步框架,可以用来实现一个依赖状态的同步器。 Provides a framework for implementing blocking locks and related synchronizers (semaphores, events, etc) that rely on first-in-first-out (FIFO) wait queues. This class is designed to be a useful basis for most kinds of synchronizers that rely on a single atomic int value to represent state. 提供一个框架,用于实现依赖先进先出(FIFO)等待队列的阻塞锁和相关同步器(信号量,事件等)。该类被设计为大多数类型的同步器的有用依据,这些同步器依赖于单个原子int值来表示状态。 This class supports either or both a default exclusive mode and a shared mode. 此类支持默认独占模式和共享模式。 Even though this class is based on an internal FIFO

可能是全网最好的MySQL重要知识点/面试题总结

拈花ヽ惹草 提交于 2020-02-27 13:26:07
标题有点标题党的意思,看了文章之后希望大家不会有这个想法,绝对干货!!!这篇花文章是我花了几天时间对之前总结的MySQL知识点做了完善后的产物,这篇文章可以用来回顾MySQL基础知识以及备战MySQL常见面试问题。 文末有公众号二维码,欢迎关注获取笔主最新更新文章,并可免费获取笔主总结的《Java面试突击》以及Java工程师必备学习资源。 @[toc] 什么是MySQL? MySQL 是一种关系型数据库,在Java企业级开发中非常常用,因为 MySQL 是开源免费的,并且方便扩展。阿里巴巴数据库系统也大量用到了 MySQL,因此它的稳定性是有保障的。MySQL是开放源代码的,因此任何人都可以在 GPL(General Public License) 的许可下下载并根据个性化的需要对其进行修改。MySQL的默认端口号是 3306 。 事务相关 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行。 事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红转账1000元,这个转账会涉及到两个关键操作就是:将小明的余额减少1000元,将小红的余额增加1000元。万一在这两个操作之间突然出现错误比如银行系统崩溃,导致小明余额减少而小红的余额没有增加,这样就不对了。事务就是保证这两个关键操作要么都成功,要么都要失败。 事物的四大特性(ACID)介绍一下? 原子性:

【Java并发工具类】原子类

泄露秘密 提交于 2020-02-27 12:55:23
前言 为保证计数器中 count=+1 的原子性,我们在前面使用的都是 synchronized 互斥锁方案,加锁独占访问的方式未免太过霸道,于是我们来介绍另一种解决原子性问题的 无锁方案:原子变量 。在正式介绍原子变量之前,我们先来总结下锁的不足,然后深入介绍原子变量。 锁的劣势 通过对共享变量加锁,使得获取到锁的线程可以采用独占方式来访问共享变量,并且对变量的修改对随后获取这个锁的其他线程都是可见的(Happens-Before规则)。 当多个线程同时请求锁时,对于没有获取到锁的线程将有可能被挂起并且在稍后才恢复运行(有时会选择自旋等待)。当线程恢复执行时,必须等待其他线程执行完它们的时间片后,才能被调度执行。我们需要知道, 在挂起和恢复线程等过程中会存在着很大的开销,并且通常存在着较长时间的中断 。 加锁方案在竞争激烈的情况下,其性能会由于上下文切换的开销和调度延迟而降低。而如果锁的持有时间非常短,那么在不恰当的时间请求锁时,线程休眠的代价将会不太划算。 加锁还存在一些缺点: 当一个线程正在等待锁时,它不能做任何其他事情。 如果一个线程在持有锁的情况下被延迟执行(例如发生了缺页错误、调度延迟、或者其他情况),那么所有需要这个锁的线程都无法执行下去。 如果被阻塞的线程优先级较高,而持有锁的线程优先级较低,那么将会导致优先级反转问题。 即使高优先级的线程可以抢先执行

高并发场景下锁的使用技巧

对着背影说爱祢 提交于 2020-02-27 11:40:55
本文来源: https://www.cnblogs.com/jackyfei/p/12142840.html 如何确保一个方法,或者一块代码在高并发情况下,同一时间只能被一个线程执行,单体应用可以使用并发处理相关的 API 进行控制,但单体应用架构演变为分布式微服务架构后,跨进程的实例部署,显然就没办法通过应用层锁的机制来控制并发了。那么锁都有哪些类型,为什么要使用锁,锁的使用场景有哪些?今天我们来聊一聊高并发场景下锁的使用技巧。 锁类别   不同的应用场景对锁的要求各不相同,我们先来看下锁都有哪些类别,这些锁之间有什么区别。 悲观锁(synchronize) Java 中的重量级锁 synchronize 数据库行锁 乐观锁 Java 中的轻量级锁 volatile 和 CAS 数据库版本号 分布式锁(Redis锁) 乐观锁   就好比说是你是一个生活态度乐观积极向上的人,总是往最好的情况去想,比如你每次去获取共享数据的时候会认为别人不会修改,所以不会上锁,但是在更新的时候你会判断这期间有没有人去更新这个数据。   乐观锁使用在前,判断在后。我们看下伪代码: 1reduce() 2{ 3 select total_amount from table_1 4 if(total_amount < amount ){ 5 return failed. 6 } 7 //其他业务逻辑 8

支持内部晋升的无锁并发优先级线程池

风格不统一 提交于 2020-02-27 09:29:25
支持内部晋升的无锁并发优先级线程池 [TOC] 引言 在技术群讨论到一个有意思的业务需求,可以描述为: 有一个内部按照优先级进行任务排序的线程池。线程池会优先执行高优先级的任务。随着时间的流逝,线程池内部低优先级的任务的优先级会逐渐晋升变为高优先级,以避免被不断新增的高优先级任务阻塞导致饿死。 考虑到 JDK 已经为开发者提供了自定义线程池 ThreadPoolExecutor 以及优先级队列 PriorityBlockingQueue ,两者相结合并且定期调整队列中低优先级任务的优先级再进行 resort 将低优先级的任务调整到队列的前头,也可以一定程度上避免被饿死。 这种方案的问题在于 resort 的消耗比较高,并且还需要重新计算每一个任务的优先级。为此,引出我们下面的设计,希望使用无锁并发的数据结构存储任务,并且任务支持自动的优先级晋升,保证低优先级的任务最终能够执行而不会被不断增加的高优先级任务饿死。 欢迎加入技术交流群186233599讨论交流,也欢迎关注笔者公众号:风火说。 推导过程 如何实现优先级晋升 声明一个数组,按照循环队列的方式使用。每一个数组槽位上都挂载一个任务列表。有一个当前指针指向数组中的某一个槽位,该槽位即为当前最高优先级任务插入的槽位。指针数字递增方向优先级依次降低。指针以某种方式沿递增方向移动,因为指针指向的槽位代表最高优先级

悲观锁与乐观锁

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

java并发编程的艺术读书笔记(一)

故事扮演 提交于 2020-02-27 08:12:58
并发编程的目的是为了程序运行的更快。 1.上下文切换: 时间片:cpu分配给各个线程的时间。 单核处理器也支持多线程执行代码。 cpu通过时间片分配算法来循环执行任务,任务从保存到再加载的过程就是一次上下文切换。 多线程不一定快,因为线程有创建和上下文切换的开销。 使用Lmbench可以测试上下文切换的时长(什么时候需要看这个参数呢)。 使用vmstat可以测量上下文切换的次数。比如:执行vmstat 1,再看cs的值,cs表示上下文切换的次数,这个值表示每一秒钟上下文切换的次数。(什么时候需要用到这个命令呢?) 减少上下文切换的方法: 1.无锁并发编程。多线程竞争锁时,会引发上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,比如将数据的ID按照Hash算法取模分段,不同的线程处理不同段的数据。 2.CAS算法。eg:java的atomic包使用CAS算法来更新数据,而不需要加锁。 3.使用最少线程。 4.使用协程。协程:在单线程里实现多线程的调度,并在单线程里维持多个线程间的切换。 减少上下文切换实战: 通过减少线上大量WAITING的线程,来减少上下文切换的次数。 第一步:用jstack命令dump线程信息,看pid为3117的进程在做什么 sudo -u admin jstack 3117>/temp 第2步:统计所有线程分别处于什么状态 grep java

聊聊 Java 的几把 JVM 级锁

喜夏-厌秋 提交于 2020-02-27 02:17:25
简介 在计算机行业有一个定律叫 " 摩尔定律 " ,在此定律下,计算机的性能突飞猛进,而且价格也随之越来越便宜,cpu从单核到了多核,缓存性能也得到了很大提升,尤其是多核cpu技术的到来,计算机同一时刻可以处理多个任务。在硬件层面的发展带来的效率极大提升中,软件层面的多线程编程已经成为必然趋势,然而多线程编程就会引入数据安全性问题,有矛必有盾,于是发明了“锁”来解决线程安全问题。在这篇文章中,总结了java中几把经典的JVM级别的锁。 synchronized synchronized关键字是一把经典的锁,也是我们平时用得最多的。在jdk1.6之前,syncronized是一把重量级的锁,不过随着jdk的升级,也在对它进行不断的优化,如今它变得不那么重了,甚至在某些场景下,它的性能反而优于轻量级锁。在加了syncronized关键字的方法、代码块中,一次只允许一个线程进入特定代码段,从而避免多线程同时修改同一数据。 synchronized锁有如下几个特点: a、有锁升级过程 在jdk1.5(含)之前,synchronized的底层实现是重量级的,所以之前一致称呼它为"重量级锁",在jdk1.5之后,对synchronized进行了各种优化,它变得不那么重了,实现原理就是锁升级的过程。我们先聊聊1.5之后的synchronized实现原理是怎样的

来自阿里的P7高级程序员教你如何成为一名合格的Java程序员

最后都变了- 提交于 2020-02-26 11:18:24
Java程序员的基本技能 基本语法 这包括static、final、transient等关键字的作用,foreach循环的原理等等。今天面试我问你static关键字有哪些作用,如果你答出static修饰变量、修饰方法我会认为你合格,答出静态块,我会认为你不错,答出静态内部类我会认为你很好,答出静态导包我会对你很满意,因为能看出你非常热衷研究技术。 集合 非常重要,也是必问的内容。基本上就是List、Map、Set,问的是各种实现类的底层实现原理,实现类的优缺点。 集合要掌握的是ArrayList、LinkedList、Hashtable、HashMap、ConcurrentHashMap、HashSet的实现原理,能流利作答,当然能掌握CopyOnWrite容器和Queue是再好不过的了。另外多说一句,ConcurrentHashMap的问题在面试中问得特别多,大概是因为这个类可以衍生出非常多的问题,关于ConcurrentHashMap,我给网友朋友们提供三点回答或者是研究方向: ConcurrentHashMap的锁分段技术 ConcurrentHashMap的读是否要加锁,为什么 ConcurrentHashMap的迭代器是强一致性的迭代器还是弱一致性的迭代器 设计模式 当然咱们不能这么功利,为了面试而学习,设计模式在工作中还是非常重要、非常有用的