CAS

Java并发基础

[亡魂溺海] 提交于 2020-08-04 19:50:51
文章目录 1.Volatile 2.CAS 3.锁 4.AQS 5.ThreadPool 1.Volatile volatile是一个关键字,用于在并发编程中修饰变量 volatile:java提供的一种 弱 同步机制 轻量的同步机制,用来确保将变量的更新通知到其他线程 保证可见性(禁止指令重排)、不保证原子性 如何保证可见性 变量声明为volatile类型后,编译器与运行时都会注意到这个变量时共享的,不会将该变量 上的操作和其他内存操作仪器重排序 volatile变量不会被缓存在寄存器 指令重排 多线程环境中,线程交替运行,编译器优化重排的存在,两个线程中使用的变量无法保持一致性 JMM(Java内存模型) JMM描述的是一组规范,通过规范来定义程序中各个变量的访问方式 jmm同步规定: 1.线程解锁前,必须把共享变量的值刷新回主内存 2.线程加锁前,必须读取主内存的最新值到自己的工作内存 3.加锁解锁是同一把锁 不保证原子性 原子性:不可分割、完整性,即某个线程正在做某个具体业务,中间不可以被加塞或者被分割,需要整体完整, 要么同时成功,要么同时失败 使用AtomicInteger,synchronized 可以保证原子性 2.CAS CompareAndSet-- 比较并设置(交换) CAS是一条CPU并发原语,体现在sun.misc.Unsafe类中各个方法 public

JUC并发基础

痴心易碎 提交于 2020-08-04 18:10:51
文章目录 一.Volatile 0.基础知识 1. volatile的解释 3.volatile的应用 二.CAS 0.CAS的定义 1.CAS底层原理 2.CAS的缺点 3.ABA问题 三.集合类并发安全 0.问题描述 1.故障现象 2.导致原因 3.解决方法 四.Java锁 0.公平锁、非公平锁 1.可重入锁(递归锁) 2.自旋锁 3.读写锁/互斥锁 五.J.U.C-AQS 0.AQS- Abstract Queued Synchronizer 1.Semaphore信号量 六.阻塞队列 0.BlockingQueue阻塞队列 1.阻塞队列的方法 2.SynchronousQueue 不存储元素的队列 3.阻塞队列的应用 4.synchronized 和lock的区别 七.线程池 1.为什么使用线程池 2.线程池 3.线程池的创建 4.实际生产的线程池的配置 八.死锁及定位分析 一.Volatile 0.基础知识 volatile关键字是java虚拟机提供的最轻量级的同步机制 JMM :Java Memory Model 可见性 Visiblity 原子性 Atomicity 有序性 Ordering 可见性 : JMM内存模型中,工作内存和主内存同步延迟现象造成了可见性问题。 为什么要使用缓存? 处理器CPU和存储设备的速度存在数量级上的差距,使用缓存Cache来解决这个问题

ReentrantLock和AQS源码深入分析

左心房为你撑大大i 提交于 2020-08-04 12:01:14
文章目录 ReentranLock和AQS的关系 非公平锁源码分析 公平锁源码分析 ReentranLock和AQS的关系 在深入分析ReentranLock和AQS之前,我们首先来理清楚一下它们的关系,AQS全名AbstractQueuedSynchronizer队列同步器,是一个能向外提供同步状态(锁)管理的基础框架,ReentranLock正是借助了它从而具备了"锁"的能力。 那么AQS是如何能做到对同步状态进行管理呢?简要来说,它有一个表示同步状态的int变量和一个队列,这个队列用来存放获取同步状态失败的线程,当线程获取同步状态失败之后,当前线程以及等待状态等信息就会被构造成为一个节点,被压进队列中,当同步状态释放时,首节点会把它的后继节点线程唤醒,使其再次尝试获取同步状态。 好像说到这么多,还是不够直观地说明它们之间地关系…接下来我们就先来看看源代码中它们之间是个什么关系吧 public class ReentrantLock implements Lock, java.io.Serializable { private final Sync sync; public void lock() { sync.lock(); } abstract static class Sync extends AbstractQueuedSynchronizer { abstract

呼叫中心中继网关参数选型

随声附和 提交于 2020-07-29 05:01:24
奥科 利用AudioCodes VolPerfect技术实现卓越的语音质量 •按需可扩展的模块化体系架构 •丰富的数字(E1/T1/J1)和模拟(FXO/FXS)接口 •经济适用的低密度网关 •当电源或网络出现问题时,生命线功能可以转到PSTN •可以转换到PSTN以确保连接 •内置的OSN模块可用于运行第三方的应用程序 •内置的基于DSP的会议模块 Mediant 1000是AudioCodes使用最新技术的节约成本的可用于无线和有线的VoIP媒体网关。智能的封装与一个可堆叠的1U机箱中,被设计用于企业和小型运营商的TDM和IP网络的接口。得益于AudioCodes创新的分组技术,MEDIANT 1000能够快速投放市场,经济可靠的部署下一代网络。 Mediant 1000基于AudioCodes领先而出色的和姓媒体网关技术VoIPerfect架构,MEDIANT 1000可将传统的电话和PBX连接到IP网络。并提供出色的语音质量。除了作为纯媒体网关之外,Mediant 1000于多家网关、交换机、网守、代理服务器、IP话机、会话边界控制器以及防火墙有良好的互通性。 可根据业务增长升级 Mediant 10000在满足服务提供商升级的需求的同时也能满足较小场所的密度需求。简约的模块化网关具有良好的可扩展性,支持1,2,4E1/T1/J1接口,或1至24个模拟FXO/FXS接口

14个Java并发容器,Java高手都知道!

江枫思渺然 提交于 2020-07-29 02:37:34
作者:acupt https://blog.csdn.net/Design407/article/details/100084673 不考虑多线程并发的情况下,容器类一般使用ArrayList、HashMap等线程不安全的类,效率更高。 在并发场景下,常会用到ConcurrentHashMap、ArrayBlockingQueue等线程安全的容器类,虽然牺牲了一些效率,但却得到了安全。 上面提到的线程安全容器都在java.util.concurrent包下,这个包下并发容器不少,今天全部翻出来鼓捣一下。 仅做简单介绍,后续再分别深入探索。 并发容器介绍 ConcurrentHashMap:并发版HashMap CopyOnWriteArrayList:并发版ArrayList CopyOnWriteArraySet:并发Set ConcurrentLinkedQueue:并发队列(基于链表) ConcurrentLinkedDeque:并发队列(基于双向链表) ConcurrentSkipListMap:基于跳表的并发Map ConcurrentSkipListSet:基于跳表的并发Set ArrayBlockingQueue:阻塞队列(基于数组) LinkedBlockingQueue:阻塞队列(基于链表) LinkedBlockingDeque:阻塞队列(基于双向链表)

JUC之ReentrantLock学习

蹲街弑〆低调 提交于 2020-07-28 20:39:40
在学习synchronized的时候,知道要实现一个锁,需要一下几点因素: 共享资源 线程阻塞和唤醒 阻塞线程存储:wait池 其次,我们知道synchronized是一个非公平的锁,当一个持有锁的线程刚刚释放掉锁的同时,恰好有个线程来抢占锁是可以抢占到锁的。而不是wait池里面的第一个线程抢占到锁。这样就产生的插队的效果。 重入锁,用起来比synchronize简单,不需要关心锁类型,只需要关心锁的范围。既然是锁,也要遵循锁的特性,需要满足上面说的3点因素,另外 重入锁支持重入,就是对于同一个线程,同一把锁,可以在上一次未释放锁之前,再次抢占到这把锁 重入锁有有两种实现:公平与非公平,非公平和synchronized差不多,公平锁的话,则不允许出现插队的情况 一、类图 二、测试 public class TestReentrantLock { private static Integer i = 0; private static ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) throws InterruptedException { //1.创建一千个线程 Thread[] threads = new Thread[1000]; for (int j = 0; j

Java容器集合经典面试题集,你不容错过的面试干货

淺唱寂寞╮ 提交于 2020-07-28 19:59:36
本文总结了Java集合容器的经典面试题,所有题目都给出了自己思考,适合面试前复习扫盲使用。不能保证里面包含了所有集合面试题,但只要认真深挖好每一道题,做到触类旁通,就能以不变应万变。 概述类面试题 1. 请说一下Java容器集合的分类,各自的集承结构 Java中的容器集合分为两大阵营,一个是Collection,一个是Map Collection下分为Set,List,Queue Set的常用实现类有HashSet,TreeSet等 List的常用实现类有ArrayList,LinkedList等 Queue的常用实现类有LinkedList,ArrayBlockingQueue等 Map下没有进一步分类,它的常用实现类有HashMap,ConcurrentHashMap等 能把上面的基本框架答出来基本就没问题了,对于各种类型我只列举了一些实际工作中常用的实现类。但其实在Set,List和Queue下还有更细的划分,如果想要在面试时表现一番,那得对着JDK好好背一背了>_< 2. 请谈一谈Java集合中的fail-fast和fail-safe机制 fail-fast是一种错误检测机制,Java在适合单线程使用的集合容器中很好地实现了fail-fast机制,举一个简单的例子:在多线程并发环境下,A线程在通过迭代器遍历一个ArrayList集合,B线程同时对该集合进行增删元素操作

面试美团,面试官突然问我 Java “锁” ,我哭了

佐手、 提交于 2020-07-28 19:29:55
前言 Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。本文旨在对锁相关源码(本文中的源码来自JDK 8)、使用场景进行举例,为读者介绍主流锁的知识点,以及不同的锁的适用场景。 Java中往往是按照是否含有某一特性来定义锁,我们通过特性将锁进行分组归类,再使用对比的方式进行介绍,帮助大家更快捷的理解相关知识。下面给出本文内容的总体分类目录: 1. 乐观锁 VS 悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度。在Java和数据库中都有此概念对应的实际应用。 先说概念。对于同一个数据的并发操作,悲观锁认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。Java中,synchronized关键字和Lock的实现类都是悲观锁。 而乐观锁认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重试)。 乐观锁在Java中是通过使用无锁编程来实现,最常采用的是CAS算法,Java原子类中的递增操作就通过CAS自旋实现的。 根据从上面的概念描述我们可以发现:

Java synchronized原理总结

喜欢而已 提交于 2020-07-28 13:29:37
锁的内存语义 synchronized的底层是使用操作系统的mutex lock实现的。 内存可见性: 同步块的可见性是由“如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行load或assign操作初始化变量的值”、“对一个变量执行unlock操作之前,必须先把此变量同步回主内存中(执行store和write操作)”这两条规则获得的。 操作原子性: 持有同一个锁的两个同步块只能串行地进入 锁的内存语义: 当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中 当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须从主内存中读取共享变量 (要看懂上面这不多的几句话,得先了解一下,最底层的8个操作lock,unlock,read,load,use,assign,store,write;工作内存:cpu的寄存器和高速缓存的抽象描述;底层是怎么实现synchronized的,使用一个monitor的enter和exit,这之间是执行同步代码块。。) 锁释放和锁获取的内存语义: 线程A释放一个锁,实质上是线程A向接下来将要获取这个锁的某个线程发出了(线程A对共享变量所做修改的)消息。 线程B获取一个锁,实质上是线程B接收了之前某个线程发出的(在释放这个锁之前对共享变量所做修改的)消息。

不会用Java Future,我怀疑你泡茶没我快, 又是超长图文!!

我的未来我决定 提交于 2020-07-28 12:42:12
你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough 现陆续将Demo代码和技术文章整理在一起 Github实践精选 ,方便大家阅读查看,本文同样收录在此,觉得不错,还请Star 前言 创建线程有几种方式?这个问题的答案应该是可以脱口而出的吧 继承 Thread 类 实现 Runnable 接口 但这两种方式创建的线程是属于”三无产品“: 没有参数 没有返回值 没办法抛出异常 class MyThread implements Runnable{ @Override public void run() { log.info("my thread"); } } Runnable 接口是 JDK1.0 的核心产物 /** * @since JDK1.0 */ @FunctionalInterface public interface Runnable { public abstract void run(); } 用着 “三无产品” 总是有一些弊端,其中没办法拿到返回值是最让人不能忍的,于是 Callable 就诞生了 Callable 又是 Doug Lea 大师,又是 Java 1.5 这个神奇的版本 /** * @see