JDK并发集合13:其他队列(并发容器)

ConcurrentLinkedQueue ConcurrentLinkedQueue没有实现BlockingQueue接口,所以不是阻塞队列,不能用于线程池中,但是它是线程安全的。它由一个无界的单向链表实现。 属性 head头指针,tail尾指针。head/tail的更新可能落后于节点的入队和出队,因为它不是直接对head/tail指针进行CAS操作的,而是对Node中的item进行操作。 private transient volatile Node<E& ...

JDK并发集合11:ConcurrentMap(并发容器)

ConcurrentMap ConcurrentMap是一个接口,定义了能够支持并发访问的map集合,定义了以下几个方法(节选): getOrDefault:获取不到则返回默认值; putIfAbsent:如果没有这个key存在,则插入默认值; computeIfAbsent:传入的是一个mappingFunction,如果key不存在则通过mappingFunction设置默认值; computeIfPresent:传入的是一个mappingFunction,如果key存在则通过mappingFunction设置默认值; compute:传入一个remappingFunction,对value进行remappingFunction运行,如果结果为空则删除key, ...

JDK并发集合10:CopyOnWrite(并发容器)

CopyOnWrite的应用场景是多线程场景下多读少写,读的时候不加锁,修改数据的时候是通过拷贝一份数据进行修改,修改完后通过锁的形式写回来更新数据的。 CopyOnWriteArrayList CopyOnWriteArrayList的类继承图: 实现List提供列表的增删改查功能。 实现RandomAccess提供随机访问。 实现Cloneable可被克隆。 实现Serializable可被序列化。 锁 使用ReentrantLock用于修改的时候加锁。与ArrayList一样,内部也是通过一个Object[]数组来存储数据的。注意array加了volatile,这样在修改的时候切换数组就可以立即生效。还加了transient,自己实现序列化方法。 /** The ...

JDK并发集合9:其他(同步工具)

CyclicBarrier CyclicBarrier是一个类似于CountDownLatch功能的类,其用于“循环栅栏”,它会阻塞一些线程直到所有线程同时到达了await再继续往下执行。和CountDownLatch区别是: 不用countdown 可复用 属性 其内部实现是使用了ReentrantLock和条件锁: 未到齐,trip.await() 到齐了,trip.signalAll() /** The lock for guarding ...

JDK并发集合8:StampedLock(同步工具)

之前的ReentrantReadWriteLock读写锁比ReentrantLock的并发度高,但是读的时候还是需要加锁,即悲观锁。我们来看一种乐观锁的实现,可以进一步提高并发度。 乐观读 StampedLock具有三种模式:写模式、读模式、乐观读模式。它比ReentrantReadWriteLock多了一种“乐观读”的模式: 读时不加锁 使用的时候发现数据被修改再升级为“悲观读” 相当于降低了“读”的地位,升高了“ ...

JDK并发集合7:AQS总结(同步工具)

其他使用AQS的并发类 Semaphore 内部Sync继承AQS: state为permit的数量 用处:做限流 CountDownLatch 内部Sync继承AQS: state保存次数 使用共享锁实现 调用await的线程阻塞在同步队列中 调用countDown的线程CAS减少state,减到0的时候一次过唤醒所有等待线程 AQS总结 之前学习了ReentrantLock、ReentrantReadWriteLock以及上面的Semaphore和CountDownLatch,我们来总结一下AQS。 state AQS里面使用一个int的状态变量state来保存同步状态,主要有两种形态: ...

JDK并发集合6:ReentrantReadWriteLock(同步工具)

读写锁是一种适用于多读少写的场景的锁,多个读线程可以用时对资源进行读取,但是写线程则是排他的。在多读少写的场景下,对比使用ReentrantLock和synchronized,能极大地提高并发度。 读写锁的特性: 互斥 读 写 读 否 是 写 是 是 类结构 ReentrantReadWriteLock本身实现了ReadWriterLock,需要实现“获取读锁” ...

JDK并发集合5:ReentrantLock(同步工具)

ReentrantLock 我们可以通过ReentrantLock来加深对AQS的理解。 内部API ReentrantLock内部的同步器Sync继承于AQS。 abstract static class Sync extends AbstractQueuedSynchronizer {} static final class FairSync extends Sync {} static final class NonfairSync ...

JDK并发集合4:AQS原理(同步工具)

接下来我们正式进入JDK并发集合的章节。 Treiber Stack Treiber Stack是一种可扩展的无锁栈,利用细粒度的并发原语CAS来实现的。在FutureTask中会用到。 入栈 单链表保存了各个元素 入栈时,首先创建一个newHead,把next指针指向top 通过CAS替换top为newHead,CAS的条件是top==oldHead 出栈 创建一个新的指针,指向top的next元素,假设其next元素为newHead CAS将top指向newHead, ...

JDK并发集合3:一致性问题(基础篇)

JMM就是为了解决多线程环境下共享变量的一致性问题,那么一致性包含哪些内容呢?它包括可见性、有序性和原子性三方面。 原子性 一个操作是不可中断的,要么全部执行成功要么全部执行失败。 JMM模型中八种操作是原子性的。 可见性 所有线程都能看到共享内存的最新状态。 JMM是通过在变更修改后同步回主内存,在变量读取前从主内存刷新变量值来实现的,它是依赖主内存的。而当某个线程的工作内存对这个变量进行修改时并没有及时同步到主内存中,这种情况下该变量对于其他线程来说是不可见的。 这里需要注意几个关键字: volatile:修改后立即刷回主内存,读取时从主内存读取 synchronized: ...

JDK并发集合2:JMM模型(基础篇)

上一篇讲到CPU提供了两个接口让用户可以自己刷新Store buffer和失效队列,这一篇我们来看下为了更好的理解如何实现同步的可见性,JMM抽象出来的内存屏障Memory Barrier。 JMM内存模型 java作为一个跨平台的语言,需要面对不同的底层硬件系统,它设计一个中间层模型来屏蔽底层的硬件差异,给上层的开发者一个一致的使用接口。JMM模型就是这样一个中间层的模型。 JMM内存模型定义: Java内存模型(Java Memory Model,JMM)是在硬件内存模型基础上更高层的抽象,它屏蔽了各种硬件和操作系统对内存访问的差异性,从而实现让Java程序在各种平台下都能达到一致的并发效果。 ...

JDK并发集合1:CPU缓存(基础篇)

CPU缓存 因为CPU运算速度和内存的读取速度相差了很多个数量级,所以在CPU这里通常会有几级缓存,如下图: 对于现代处理起来说,一个CPU通常有两个逻辑线程,如上图的Core0和Core1。每个Core有自己的L1 Cache,其中又分为存储指令的L1i和存储数据的L1d。同一个物理CPU的逻辑核心共享同一个L2 Cache,所有的物理CPU共享L3 Cache,这三层Cache的速度对比如下: L1:紧靠CPU内核 L2:比L1大一些,慢一些 ...

jmap

jmap JVM Memory Map命令用于生成heap dump文件,如果不使用这个命令,还可以使用-XX:+HeapDumpOnOutOfMemoryError参数来让虚拟机出现OOM的时候自动生成dump文件。 jmap不仅能生成dump文件,还可以查询finalize执行队列、Java堆和永久代的详细信息,如当前使用率、当前使用的是哪种收集器等。【内存分析】 [root@localhost jdk1.7.0_79] ...

jstack

一、jstack 介绍 jstack是java虚拟机自带的一种堆栈跟踪工具。jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使用方式只支持以下的这种方式: jstack [-l] pid 主要分为两个功能: a. 针对活着的进程做本地的或远程的线程dump; b. 针对core文件做线程dump。 ...

perf

安装 yum install -y perf perf性能分析: 生成火焰图(执行1-4步骤): 1、perf record -e cpu-clock -g -p pid (perf record -F 99 ...

Redis开发指南

基本数据类型 数据类型 String 值类型可以是:字符串、数字、二进制 最大不超过512M Hash 键值对结构 ziplist 元素个数 < hash-max-ziplist-entries(默认512) 所有的值 < hash-max-ziplist-value(默认64字节) 比hashtalbe节省内存 ...

iostat

1、切换root 2、需要安装下 yum install -y sysstat 3、iostat 参数介绍: -d 显示磁盘使用情况, -x 显示详细信息 -k 以KB为单位 1 1: 频率1秒1次, ...

synchronized源码分析

monitorenter 获取锁是通过monitorenter,我们来看下源码实现 IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, BasicObjectLock* elem)) #ifdef ASSERT thread->last_frame( ...

Object的wait/notify方法

背景 上一篇说到LockSupport的park/unpark,这一篇就来说说Object的wait/notify方法。 Object是一切类的父类,wait方法是在Object中实现的。 public final native void wait(long timeout) throws InterruptedException; wait ObjectSynchronizer Object的wait是在ObjectSynchronizer中实现的。注意: ...

redis中scan命令的实现

在一个天朗气清的日子,小灰登上了线上的redis打算查询数据。然而他只记得前缀而不知道整个键是多少,于是在命令行敲入了“keys xxx*”命令。 瞬间服务卡死,报警邮件堆满了邮箱,而小灰,只能目瞪狗呆的等待着即将降临的case study。 基本上,keys *命令都是在线上是被运维禁止的。 redis的键在键值对大小大于hash-max-ziplist-value且个数小于hash-max-ziplist-entries的时候,是存放在散列表数据结构中的,在运行keys命令的时候,需要遍历数据库键空间,把所有键都取出来后与keys后面的pattern匹配。 ...

Park/Unpark源码

背景 在读JUC源码的时候经常看到LockSupport.park/unpark阻塞和唤醒线程,我们来看看它们和Object的wait/signal有什么区别。 unpark LockSupport.java public static void unpark(Thread thread) { if (thread != null) UNSAFE.unpark( ...

条件变量singal与unlock的顺序

背景 在看hotsport源码的时候遇到一段signal与unlock顺序不一样的代码,在Parker::unpark里面: if (WorkAroundNPTLTimedWaitHang) { status = pthread_cond_signal (&_cond[_cur_index]); assert (status == 0, "invariant" ...

ES添加停用词

构建停用词 添加索引 构建停用词,注意stopwords.txt必须在每个es的config目录下。 PUT http://<ip>/my_index_new_new { "settings": { "analysis" ...

编译tensorflow-serving GPU

背景 因为业务方上了bert的模型,所以要制作一个GPU版本的sidecar的TFServing镜像。 编译 找到一种可以直接通过docker编译,不用在主机上装各种东西的方法:使用devel版本的镜像。 devel镜像 TFServing-devel版本的镜像自带了很多编译Tensorflow Serving的组件,比如bazel、gcc、glibc等等等等,因此会非常大。打好镜像后我们把bin文件拷贝到非devel版本的镜像里面运行即可。 去dockerhub拉镜像:https://hub.docker.com/ ...

插件化框架

因为在写一个多租户可用的框架,希望在上线的时候各个租户能够尽量做到互不影响,所以写了一个插件化加载的方法。中间踩了不少坑,写篇文章记一下。 1 获取ClassLoader 1.1 上游获取ClassLoader /** * 反射设置addUrl为可达 * @return */ private static Method initAddMethod(){ try{ Method add = URLClassLoader. ...

redis缓存

缓存的三种问题 缓存穿透:大批量请求不存在的key,导致数据库压力增大。【解决方案】:布隆过滤器。 缓存击穿:同一时间大批量请求一个过期的key,导致这些请求在同一时间访问数据库。【解决方案】:获取数据库后回写这个过程申请分布式锁,只有一个请求能获取后回写,其他一直重试等待。 缓存雪崩:同一时间大批量key过期。【解决方案】:设置expire time的时候随机加1~5分钟的超时。 数据库和缓存一致性解决: ...

buffer和cache的区别

linux:buffer是缓存裸设备的读写,cache是缓存文件系统的读写。 应用系统:buffer主要为了解决CPU和其他存储设备之间速度不对等的问题,比如编辑编写错误的时候使用。定期会刷新; cache主要用于在内存中缓存原本需要从磁盘读取的数据。 refer:http://www.differencebetween.net/technology/hardware-technology/difference-between-cache-and-buffer/ ...