CAS

Java并发-多线程面试(全面)

只愿长相守 提交于 2020-04-24 20:27:13
1. 什么是线程? 2. 什么是线程安全和线程不安全? 3. 什么是自旋锁? 4. 什么是Java内存模型? 5. 什么是CAS? 6. 什么是乐观锁和悲观锁? 7. 什么是AQS? 8. 什么是原子操作?在Java Concurrency API中有哪些原子类(atomic classes)? 9. 什么是Executors框架? 10. 什么是阻塞队列?如何使用阻塞队列来实现生产者-消费者模型? 11. 什么是Callable和Future? 12. 什么是FutureTask? 13. 什么是同步容器和并发容器的实现? 14. 什么是多线程?优缺点? 15. 什么是多线程的上下文切换? 16. ThreadLocal的设计理念与作用? 17. ThreadPool(线程池)用法与优势? 18. Concurrent包里的其他东西:ArrayBlockingQueue、CountDownLatch等等。 19. synchronized和ReentrantLock的区别? 20. Semaphore有什么作用? 21. Java Concurrency API中的Lock接口(Lock interface)是什么?对比同步它有什么优势? 22. Hashtable的size()方法中明明只有一条语句”return count”,为什么还要做同步? 23.

灵魂拷问:Java对象的内存分配过程是如何保证线程安全的?(阿里面试)

荒凉一梦 提交于 2020-04-24 16:56:46
JVM内存结构,是很重要的知识,相信每一个静心准备过面试的程序员都可以清楚的把堆、栈、方法区等介绍的比较清楚。 上图,是一张在作者根据《Java虚拟机规范(Java SE 8)》中描述的JVM运行时内存区域结构画的。 很多人都知道Java对象是在堆内存中分配空间的(JIT优化除外),也知道内存分配过程中是线程安全的,那么虚拟机到底是如何保证线程安全的呢?本文就来简单介绍一下。 1.Java对象的内存分配 我们知道,Java是一门面向对象的语言,我们在Java中使用的对象都需要被创建出来,在Java中,创建一个对象的方法有很多种,如使用new、使用反射、使用Clone方法等,但是无论如何,对象在创建过程中,都需要进行内存分配。 拿最常见的new关键字举例,当我们使用new创建对象后代码开始运行后,虚拟机执行到这条new指令的时候,会先检查要new的对象对应的类是否已被加载,如果没有被加载则先进行类加载。 在类加载检查通过之后,就需要给对象进行内存分配了,分配的内存主要用来存放对象的实例变量。 在进行内存分配时,需要根据对象中的实例变量情况等信息确定需要分配的空间大小,然后从Java堆中划分出这样一块区域(假设没有JIT优化)。 根据JVM使用的垃圾回收器的类型,因其回收算法不同,会导致堆中内存分配情况不同。如标记-清楚算法回收后的内存中会有大量不连续的内存碎片,在给新的对象分配的时候

浅析CAS与AtomicInteger原子类

孤者浪人 提交于 2020-04-23 22:33:51
一:CAS简介 CAS:Compare And Swap(字面意思是比较与交换),JUC包中大量使用到了CAS,比如我们的atomic包下的原子类就是基于CAS来实现。区别于悲观锁synchronized,CAS是乐观锁的一种实现,在某些场合使用它可以提高我们的并发性能。 在CAS中,主要是涉及到三个操作数,所期盼的旧值、当前工作内存中的值、要更新的值,仅当所期盼的旧值等于当前值时,才会去更新新值。 二:CAS举例 比如当如下场景,由于i++是个复合操作,读取、自增、赋值三步操作,因此在多线程条件下我们需要保证i++操作的安全 public class CASTest { int i = 0 ; public void increment() { i ++ ; } } 解决办法有通过使用synchronized来解决,synchronized解决了并发编程的原子性,可见性,有序性。 public class CASTest { int i = 0 ; public synchronized void increment() { i ++ ; } } 但synchronized毕竟是悲观锁,尽管它后续进行了若干优化,引入了锁的膨胀升级措施,但是还是存在膨胀为重量级锁而导致阻塞问题,因此,我们可以使用基于CAS实现的原子类AtomicInteger来保证其原子性 public

JAVA concurrency -- CyclicBarrier 与 CountDownLatch 源码详解

那年仲夏 提交于 2020-04-23 22:00:04
概述 CountDownLatch 和 CyclicBarrier 有着相似之处,并且也常常有人将他们拿出来进行比较,这次,笔者试着从源码的角度分别解析这两个类,并且从源码的角度出发,看看两个类的不同之处。 CountDownLatch CountDownLatch 从字面上来看是一个计数工具类,实际上这个类是用来进行多线程计数的JAVA方法。 CountDownLatch 内部的实现主要是依靠 AQS 的共享模式。当一个线程把 CountDownLatch 初始化了一个 count 之后,其他的线程调用 await 就会阻塞住,直到其他的线程一个一个调用 countDown 方法进行 release 操作,把 count 的值减到0,即把同步锁释放掉, await 才会进行下去。 Sync 内部主要还是实现了一个继承自 AQS 的同步器 Sync 。 Sync 源码如下: private static final class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 4982264981922014374L; // 构造方法,参数是count的数值 Sync(int count) { // 内部使用state来存储count setState

java中的CAS乐观锁

╄→гoц情女王★ 提交于 2020-04-23 15:34:15
最近,总是听到同事在面试的时候问候选人java中的锁相关的知识,大部分同学在问到CAS的时候会有些一知半解; 1. 原子操作 说到原子操作,会想到数据库事务中的原子性,道理都差不多,指一行或多行代码要么都执行成功或失败。 比如:i++这行代码,在执行的过程中会分为三步去执行: 1.取出i的值; 2.将i的值+1; 3.将+1后的赋值给i; 在单线程的情况下,这种操作不会有问题,但是多线程的情况下呢: 出现了线程B的结果将线程A的结果覆盖的情况;那就可以说i++不是原子操作; 可以本地验证下是不是这样的: private static int count = 0; public static void add() { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } count++; } public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(100); for(int i=0;i<100;i++){ new Thread(() -> { add(); countDownLatch

Java多线程并发08——锁在Java中的应用

£可爱£侵袭症+ 提交于 2020-04-23 07:25:46
前两篇文章中,为各位带来了,锁的类型及锁在Java中的实现。接下来本文将为各位带来锁在Java中的应用相关知识。关注我的公众号「Java面典」了解更多 Java 相关知识点。 锁在Java中主要应用还是在JUC(java.util.concurrent)包下的相关类,常用的主要有原子类、原子集合以及阻塞队列。 原子类(Atomicxxx) AtomicLong AtomicInteger、AtomicLong 和 AtomicBoolean 这3个基本类型的原子类的原理和用法相似。 作用 对 Long 进行原子操作。 在32位操作系统中,64位的 long 和 double 变量由于会被 JVM 当作两个分离的 32 位来进行操作,所以不具有原子性。而使用 AtomicLong 能让 long 的操作保持原子型。 实现原理 AtomicLong 主要依赖 CAS 原理实现。以 incrementAndGet() 为例,其实现原理如下: incrementAndGet() 首先会根据 get() 获取 AtomicLong 对应的 long 值; incrementAndGet() 接着将 current 加 1,然后通过 CAS 函数,将新的值赋值给 value。 AtomicIntegerArray AtomicIntegerArray、AtomicLongArray

本地操作系统备份还原介绍

我的梦境 提交于 2020-04-23 04:54:03
互联网技术发展的近几年,数据灾备领域也发生了一些重大变革。与互联网的其他领域一样,云计算技术已到业务的开发与应用。将云集成到备份和灾难恢复应用中,灵活的实现了传统灾备方式不具备的交付方式和功能。 关于UCACHE企业级云灾备的一些功能实现: 勒索病毒防护 保护企业的核心数据免遭这类勒索软件加密或锁定降低企业生存风险。 文件系统备份/恢复 保护企业的非结构化数据,满足全量备份和增量备份要求。 云平台备份/恢复 保护企业的自建云平台运营安全,兼容Openstack、CAS、FusionCloud等云平台。 虚拟化备份/恢复 保护企业的虚拟化平台数据运营安全,兼容VMware、Hyper-v、XenServer等虚拟化平台。 数据库备份/恢复 持续性数据保护帮助企业数据库等应用备份RPO≈“0”保障核心数据运营安全,支持DB2\ \MySQL\Oracle\SAP HANA\SQL等。 数据迁移工具 一站式帮助企业不中断,高效无缝迁移业务,为云转移、设备替换、业务割接场景,提供了搬迁、校验、同步、加密等完美体验。 UCACHE灾备云本地数据保护应用场景 UCACHE云灾备保护本地机房物理数据,包括办公文件,设计稿,音视频,医疗影像等重要文件,虚拟机配置及数据文件,操作系统、磁盘卷级备份DB2 、 GaussDB 、 GBase 、 MySQL 、 Oracle 、 SAP HANA 、

300 行代码带你搞懂 Java 多线程!

青春壹個敷衍的年華 提交于 2020-04-23 04:42:20
作者:永远在路上 https://blog.csdn.net/weixin_44104367/article/details/104481510 线程 线程的概念,百度是这样解释的: 线程(英语:Thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。 在Unix System V及SunOS中也被称为轻量进程(Lightweight Processes),但轻量进程更多指内核线程(Kernel Thread),而把用户线程(User Thread)称为线程。 1.1 线程与进程的区别 进程:指在系统中正在运行的一个应用程序;程序一旦运行就是进程;进程——资源分配的最小单位。 线程:系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元执行流。线程——程序执行的最小单位。 也就是,进程可以包含多个线程,而线程是程序执行的最小单位。推荐看下这篇: 通俗易懂的理解进程与线程 。 1.2 线程的状态 NEW:线程刚创建 RUNNABLE: 在JVM中正在运行的线程,其中运行状态可以有运行中RUNNING和READY两种状态,由系统调度进行状态改变。 BLOCKED:线程处于阻塞状态,等待监视锁,可以重新进行同步代码块中执行 WAITING

嘿嘿,我就知道面试官接下来要问我 ConcurrentHashMap 底层原理了,看我怎么秀他

混江龙づ霸主 提交于 2020-04-23 01:48:44
前言 上篇文章介绍了 HashMap 源码后,在博客平台广受好评,让本来己经不打算更新这个系列的我,仿佛被打了一顿鸡血。真的,被读者认可的感觉,就是这么奇妙。 然后,有读者希望我能出一版 ConcurrentHashMap 的解析。所以,今天的这篇文章,我准备讲述一下 ConcurrentHashMap 分别在JDK1.7和 JDK1.8 的源码。文章较长,建议小伙伴们可以先收藏再看哦~ 说一下为什么我要把源码解析写的这么详细吧。一方面,可以记录下当时自己的思考过程,也方便后续自己复习翻阅;另一方面,记录下来还能够帮助看到文章的小伙伴加深对源码的理解,简直是一举两得的事情。 更正错误 另外,上一篇文章,有个错误点,却没有读者给我指正出来。o(╥﹏╥)o 。因此,我只能自己在此更正一下。见下面截图, put 方法,在新值替换旧值那里,应该是只有一种情况的,e 不包括新值。图中的方框也标注出来了。因为,判断 e=p.next==null , 然后新的节点是赋值给 p.next 了,并没有赋值给 e,此时 e 依旧是空的。所以 e!=null,代表当前的 e 是已经存在的旧值。 文章编写过程,难免出现作者考虑不周的地方,如果有朋友发现有错误的地方,还请不吝赐教,指正出来。知错能改,善莫大焉,对于技术,我们应该怀有一颗严谨的心态~ 文章目录 这篇文章,我打算从以下几个方面来讲。 1

Java多线程并发05——那么多的锁你都了解了吗

ぐ巨炮叔叔 提交于 2020-04-22 08:58:29
在多线程或高并发情境中,经常会为了保证数据一致性,而引入锁机制,本文将为各位带来有关锁的基本概念讲解。关注我的公众号「Java面典」了解更多 Java 相关知识点。 根据锁的各种特性,可将锁分为以下几类: 乐观锁/悲观锁 独享锁(互斥锁)/共享锁(读写锁) 可重入锁 公平锁/非公平锁 分段锁 偏向锁/轻量级锁/重量级锁 自旋锁 乐观锁/悲观锁 乐观锁与悲观锁并不是特指某两种类型的锁,是人们定义出来的概念或思想,主要是指看待并发同步的角度。 乐观锁 前提 :认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁; 实现 :在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。 应用 :在 Java 中 java.util.concurrent.atomic 包下面的原子变量类就是使用了乐观锁的一种实现方式CAS(Compare and Swap 【比较并交换】)实现的。CAS 是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。 悲观锁 前提 :认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改; 实现 : 总是假设最坏的情况,以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会阻塞直到拿到锁