CAS

4W字的后端面试知识点总结(持续更新)

怎甘沉沦 提交于 2020-08-10 14:42:45
点赞再看,养成习惯,微信搜索【 三太子敖丙 】关注这个互联网苟且偷生的工具人。 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点、资料以及我的系列文章。 前言 前段时间敖丙不是在复习嘛,很多小伙伴也想要我的复习路线,以及我自己笔记里面的一些知识点,好了,丙丙花了一个月的时间,整整一个月啊,给大家整理出来了。 一上来我就放个大招好吧,我的复习脑图,可以说是全得不行,为了防止被盗图,我加了水印哈。 这期看下去你会发现很硬核,而且我会持续更新,啥也不说了,看在我熬夜一个月满脸痘痘的份上,你可以点赞了哈哈。 注:如果图被压缩了,可以去公众号【三太子敖丙】回复【复习】获取原图 Spring Spring框架的七大模块 Spring Core:框架的最基础部分,提供 IoC 容器,对 bean 进行管理。 Spring Context:继承BeanFactory,提供上下文信息,扩展出JNDI、EJB、电子邮件、国际化等功能。 Spring DAO:提供了JDBC的抽象层,还提供了声明性事务管理方法。 Spring ORM:提供了JPA、JDO、Hibernate、MyBatis 等ORM映射层. Spring AOP:集成了所有AOP功能 Spring Web:提供了基础的 Web 开发的上下文信息,现有的Web框架,如JSF

包罗万象——JAVA中的锁,一篇文章让你搞懂这个知识点

大兔子大兔子 提交于 2020-08-10 12:06:36
一、乐观锁 VS 悲观锁 悲观锁 和 乐观锁 大概是大家听到最多的两种锁了,这两种锁的区分更多的是思想上。 对于一个操作,悲观锁认为自己在操作过程中,一定有别的线程也要来修改这个数据,所以一定会加锁。而乐观锁则不认为会有别的线程来干扰自己,所以不需要加锁。 在Java中,synchronized关键字和Lock的实现类都是悲观锁,而乐观锁一般采用无锁编程,也就是CAS算法来实现的。 首先说一说悲观锁 1、悲观锁 悲观锁的流程: 1、线程尝试去获取锁 2、线程加锁成功并执行操作,其他线程等待,线程加锁失败则等待获取锁(这里有好几种办法,在synchronized中,会有在四种状态中改变,在下文中我会介绍这四种情况) 3、线程执行完毕释放锁,其他线程获取锁 通过图片和文字,我们能看出悲观锁适合写操作多的场景,加锁可以确保数据的安全,但是会影响一些操作效率。 2、乐观锁 乐观锁的流程: 1、线程直接获取同步资源数据 2、判断内存中的同步数据是否被其他线程修改 3、没有被修改则直接更新 4、如果被其他线程修则选择报错或者重试(自旋) 和悲观锁不同,乐观锁明显不适合经常进行修改,因为谁也不能保证不会出现数据安全的问题,所以乐观锁适合读操作的场景。对于读操作来说,加锁只会影响效率。 上文说到了,乐观锁一般采用CAS算法来实现,那么我们就来讲讲什么是CAS算法 3、CAS算法 CAS的英语是

浅析 CompletableFuture的无锁栈机制

半城伤御伤魂 提交于 2020-08-10 10:58:09
这几天在看公司的BinLogRelover的时候, 看到大佬在WIKI里面特意指出,为何使用Guava提供的ListenableFuture来做一些回调功能, 而且还指出在高并发的场景下Java8提供的 CompletableFuture 并不如人意,其实我个人还是比较喜欢 CompletableFuture 的, 哈哈, 可能是以前写代码用的比较多吧。 ListenableFuture 用的不是很多, 所以优缺点也说不清楚, 但是 CompletableFuture 经常让人诟病的大概包含两点吧, cancel(true) 大家使用 CompletableFuture 肯定都是想使用他的异步编排能力,但是CompletableFuture在实现Future接口的同事,却做了一些改变, 例如cancel()方法,一不小心就会踩坑。 在FutureTask中,cancel()会根据参数选择是否中断执行线程, 这一点在一些框架代码中经常会用到, public boolean cancel ( boolean mayInterruptIfRunning ) { if ( ! ( state == NEW && UNSAFE . compareAndSwapInt ( this , stateOffset , NEW , mayInterruptIfRunning ?

Java面试史上最全的JAVA专业术语面试100问 (前1-50)

让人想犯罪 __ 提交于 2020-08-10 09:44:43
前言: 说在前面, 面试题是根据一些朋友去面试提供的,再就是从网上整理了一些。 先更新50道,下一波吧后面的也更出来。 求赞求关注!! 废话也不多说,现在就来看看有哪些面试题 1、面向对象的特点有哪些? 抽象、继承、封装、多态。 2、接口和抽象类有什么联系和区别? 3、重载和重写有什么区别? 4、java有哪些基本数据类型? 5、数组有没有length()方法?String有没有length()方法? 数组没有length()方法,它有length属性。 String有length()方法。 集合求长度用size()方法。 6、Java支持的数据类型有哪些? 什么是自动拆装箱? 7、int 和 Integer 有什么区别? 8、Java类的实例化顺序? 父类静态成员和静态代码块 -> 子类静态成员和静态代码块 -> 父类非静态成员和非静态代码块 -> 父类构造方法 -> 子类非静态成员和非静态代码块 -> 子类构造方法 9、什么是值传递和引用传递? 10、String能被继承吗?为什么? 11、String和StringBuilder、StringBuffer的区别? StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况(是线程不安全的) StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况(一般很少)(是线程安全的) 首先说运行速度

RestTemplate--SpringCloud 二:

旧巷老猫 提交于 2020-08-10 08:47:30
一. 什么是RestTemplate 优雅的HTTP请求: 传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient。不过此种方法使用起来太过繁琐。 spring提供了一种简单便捷的模板类来进行操作,这就是RestTemplate。 二.一个简单的例子。 定义一个简单的restful接口 @RestControllerpublic class TestController { @RequestMapping(value = "testPost", method = RequestMethod.POST) public ResponseBean testPost(@RequestBody RequestBean requestBean) { ResponseBean responseBean = new ResponseBean(); responseBean.setRetCode("0000"); responseBean.setRetMsg("succ"); return responseBean; }} 使用RestTemplate访问该服务 //请求地址 String url = "http://localhost:8080/testPost"; //入参 RequestBean requestBean = new RequestBean(

CAS 到底是嘛玩意

爱⌒轻易说出口 提交于 2020-08-10 05:54:54
什么是 CAS ? CAS : (Compare And Swap) 比较和交换, Java 就是通过 CAS 来实现原子操作的 ! 如何使用 CAS ? CAS 需要三个操作数, 分别是 : 内存地址, 旧的预期值, 准备设置的新值 CAS执行时, 对于一个变量 V, 他的旧的预期值为 A, 将要修改的值为 B, 有且仅当 V 符合 A, 处理器才会将 A 换成 B, 否者操作失败. 在 JDK 5之后, Java 类库才开始使用 CAS 操作, 该操作被封装在 sun.misc.Unsafe 类中, 如果你用过 java.util.concurrent.atomic 包中的类, 那么你一定对它不陌生, 所有的原子操作类, 底部调用的都是 Unsafe 的API 由于 Unsafe 并没有开源, 但是可以使用 IDEA 进行反编译看到源码 : // UnSafe 类提供的方法, 用于 CAS 操作, 传入三个参数, // 依次为: 要操作的对象, 旧的预期值, 和需要设置的新值 public final int getAndAddInt ( Object var1 , long var2 , int var4 ) { int var5 ; do { // 获取 var1 的最新值 var5 = this . getIntVolatile ( var1 , var2 ) ; }

【杂谈】Disruptor——RingBuffer整理(一)

[亡魂溺海] 提交于 2020-08-10 02:30:31
纯CAS为啥比加锁要快? 同样是修改数据,一个采用加锁的方式保证原子性,一个采用CAS的方式保证原子性。 都是能够达到目的的,但是常用的锁(例如显式的Lock和隐式的synchonized),都会把获取不到锁的线程挂起,相对于CAS的不挂起,多了挂起和唤醒的开销。 尾指针是如何管理的,如何防止覆盖旧数据? 别的帖子都说RingBuffer中不维护尾指针,尾指针由消费者维护(所谓维护指针,就是修改、移动指针)其实这一句话有点误导性,如果RingBuffer不知道尾部在哪里,那它的数据存储肯定就会出问题,例如把还没消费过的数据给覆盖了。 确实,消费者会自行维护自己的消费指针,RingBuffer也不会去干涉消费者指针的维护,但是它会引用所有消费者的指针,读取他们的值,以此作为“尾部”的判断依据。实际上就是最慢的那个消费者为准。 注:消费者指针是消费者消费过的最后一条数据的序号 我们直接来看代码,这个是RingBuffer的publishEvent方法,我们看到,它首先取得一个可用的序列号,然后再将数据放入该序列号的对应位置中。我们来看看这个序列号是如何取得的。 @Override public void publishEvent(EventTranslator<E> translator) { final long sequence = sequencer.next();

深入理解JVM(③)Java的锁优化

时间秒杀一切 提交于 2020-08-10 02:20:39
前言 从JDK5到JDK6HotSpot虚拟机开发团队花费了大量的资源实现了各种锁优化技术,如 适应性自旋(Adaptive Spinning) 、 锁消除(Lock Elimination) 、 锁膨胀(Lock Coarsening) 、 轻量级锁(LightEight Locking) 、 偏向锁(Biased Locking)等 ,这些技术都是胃了在线程之间更高效地共享数据及解决竞争问题,从而提供程序的执行效率。 自旋锁与自适应锁 在Java中锁起到的作用是互斥同步,而互斥同步对性的影响最大的是阻塞,阻塞是通过挂起线程和恢复线程来实现的,这个操作是很昂贵的,消耗的服务器资源比较大。针对于此虚拟机开发团队发明了自旋锁, 因为在共享数据的锁定状态只会持续很短一段时间,为了这段时间去挂起和恢复线程很不值得。所以在一个线程获得锁的同时另一个线程可以先“稍等一会儿”,但并不放弃处理器执行时间,为了让线程等待,只须让线程执行一个忙循环(自旋),这就是自旋锁。 那么这个自旋锁的自旋时间多久比较合适呢? 如自旋时间太短那就起不到自旋的作用了,太长又会占用过多的处理器资源。所以在JDK1.4.2中引入自旋锁的时候,就提供了自旋次数为10默认值以及可以自行配置的参数-XXPreBlockSpin。 在JDK1.6中对自旋锁进行了优化,引入了自适应自旋

你真的懂 synchronized 吗?

对着背影说爱祢 提交于 2020-08-10 02:08:33
synchronized 的三种使用方式 加在非 static 方法上 (锁的是 this 对象) 加在 static 方法 上 (锁的是 Class 对象) 代码块 (锁的是 括号 中的对象) 在实现同步的时候, 大多数开发人员直接使用 synchronized 关键字, 那你真的了解 synchronized 底层原理吗? 字节码层级 synchronized被编译成 class 文件, 翻译成字节码指令有两个重要的指令 : monitorenter monitorexit , 可以发现有两个 monitorexit , 一个是正常退出, 另一个是异常退出, 所以 synchronized 不会造成死锁 使用 idea 插件, 可以查看字节码指令 JVM层级 我们知道 synchronized 锁的是对象, 那么如何判断对象是否 “锁住” 呢? synchronized 使用的锁是存在对象的 对象头 之中 JVM 规范有这样一句话 : JVM 基于进入和退出 monitor 实现代码同步, 任何对象都有一个 monitor 与之关联, 当 monitor 被持有后, 它将处于锁定状态 操作系统层级 在 JDK1.6 之前, synchronized 是重量级锁, Java 进程是工作在用户态空间上的, 如果需要实现同步, 就必须使用内核的互斥锁, 那就需要 OS

Java并发编程的艺术[2]

帅比萌擦擦* 提交于 2020-08-09 23:26:46
杀死一个开发,只需要变更三次需求。 2.1-volatile的应用(wall la tai l 还是 wall lei tai l) 它在多处理器开发中保证了共享变量的“可见性”。可见性的意思是当一个线程 修改一个共享变量时,另外一个线程能读到这个修改的值,它不会引起线程上下文的切换和调度 CPU术语定义 volatile是如何来保证可见性的呢?让我们在X86处理器下通过工具获取JIT编译器生成的 汇编指令来查看对volatile进行写操作时,CPU会做什么事情。 Java代码如下。 instance = new Singleton(); // instance是volatile变量 转变成汇编代码,如下。 0x01a3de1d: movb $0×0,0×1104800(%esi);0x01a3de24: lock addl $0×0,(%esp); Lock前缀的指令在多核处理器下会引发了两件事情[1]。 1)将当前处理器缓存行的数据写回到系统内存。 2)这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效。 2.volatile的使用优化 著名的Java并发编程大师Doug lea在JDK 7的并发包里新增一个队列集合类Linked- TransferQueue,它在使用volatile变量时,用一种追加字节的方式来优化队列出队和入队的性 能