多线程
文章平均质量分 60
蒙太纳奇
如狼一样的不息
展开
-
6-java内存模型(JMM):共享内存的并发模型
java内存模型(JMM):共享内存的并发模型 模型结构:内存可见性 问题 如果线程t1更新后数据并没有及时写回到主存,而此时线程t2读到的是过期的数据,出现脏读现象。 处理方案 使用同步机制synchronized,lock等控制不同线程间操作发生的相对顺序来解决。使用volatile关键字,使得volatile变量每次都能够强制刷新到主存,从而对每个线程都是可见...原创 2018-11-29 11:04:09 · 740 阅读 · 0 评论 -
27-介绍下Executor架构
介绍下Executor架构Execuotr是一个基于生产-消费者模型的异步处理架构。可实现线程的提交,与线程的执行过程的解耦。主要包括三个方向: 任务架构: 以Runnable,Callable接口实现的任务对象;其中Callable接口实现的任务对象,可获取其执行结果,同时可抛出异常由调用端进行处理。 任务提交执行架构: 基于生产者消费者模型实现的以Executor,...原创 2018-12-05 09:00:19 · 116 阅读 · 0 评论 -
28-任务架构
任务架构: Callable和Runnable对比 Runnable abstract void run() 不可抛出异常,不可获取异步执行结果 单一启动: 通过t.start()方法启动 线程池提交: void threadPoolExecutor.executr(runnable) Future thre...原创 2018-12-05 09:00:44 · 169 阅读 · 0 评论 -
29-异步任务提交执行架构
异步任务提交执行架构 类关系图 示例:线程池提交Runnable任务 示例:线程池提交Callable任务 Executor 线程提交接口 Executor(Runnable c):将Runnable任务提交到线程池中 ExecutorService 线程池接口 提交异步任务方法: execute(Runnable c): 向线...原创 2018-12-05 09:02:59 · 252 阅读 · 0 评论 -
30-异步任务执行结果架构
异步任务执行结果架构 应用场景 在非阻塞模型中,通常需要根据异步的执行结果决定采取对应的操作。通过实现Callback接口,并用Future可以来接收多线程的执行结果。 示例:非线程池方式获取Future实例 通过实现Callable接口并重写call()方法(返回值为一个泛型对象),建立一个异步的回调对象call;使用call初始化一个FutureTask对象 ft,并初始化/启...原创 2018-12-05 09:04:10 · 297 阅读 · 0 评论 -
1-多线程基础概念
多线程基础概念 进程,线程 进程 操作系统进行资源(包括cpu、内存、磁盘IO等)分配的最小单位;进程创建以及切换开销大;资源分配的基本单位。 线程 资源调度的基本单位。如打开的微信,浏览器,是一个进程;但是可能包含多个子任务,即多个线程。线程之间的切换,称为时间片轮转法 串行,并发,并行 串行 多个任务,执行时一个执行...原创 2018-11-28 18:30:04 · 100 阅读 · 0 评论 -
2-线程的实例化方式
线程的实例化方式 Java线程有三种实例化方法 继承 Thread实现Runnable接口实现Callable接口:Java.util.concurrent 继承Thread类 继承Thread类,重写run()方法。通过t.start()方法调用。 实现Runnable接口 自定义类MyRunnable 实现 Runnable接口,并重写run()方法(返回值为...原创 2018-11-28 18:30:38 · 742 阅读 · 0 评论 -
3-线程的常用方法
Object的相关方法 wait():线程进入等待状态 必须使用在synchronized(obj)代码块之内,即将当前线程阻塞在同步对象锁obj上。当前线程释放锁以及CPU执行权,进入等待状态;直至等待时间结束或者被notify()唤醒之后,才进入可运行状态;之后待再次获取cpu执行权以及锁时,执行wait()后的代码。 Notify(),notifyAll()...原创 2018-11-28 18:32:21 · 150 阅读 · 0 评论 -
4-线程的生命周期
线程的生命周期 New 初始化 当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread(); Runnable 可运行 调用start()方法后处于可运行状态。此时未获得CPU执行权。 Running 运行中 Runnable的线程,在获取CPU执行权后,进入运行状态 Block 阻塞 运行中的线程,由于某种原因,丧失CPU执行...原创 2018-11-28 18:33:57 · 170 阅读 · 0 评论 -
5-并发编程的机制研究
并发编程的机制研究 生活实例模型 小明妈妈做好饭,喊小明吃饭。通过在家里留字条的方式,称为读写共享变量(JMM主要是通过该方式完成的);通过打电话的方式,称为通知机制。 并发编程的通信机制 读-写共享变量:while条件中的共享变量用于线程之间的通讯 等待通知机制:通过wait() notify()机制唤醒对应的线程 出现线程安全的原因: 主内存和工作内存数据...原创 2018-11-28 18:34:30 · 81 阅读 · 0 评论 -
23-Semaphore 信号量
Semaphore 信号量 使用场景 经常用于限制获取某种资源的线程数量。比如说操场上有5个跑道,一个跑道一次只能有一个学生在上面跑步,一旦所有跑道在使用,那么后面的学生就需要等待,直到有一个学生不跑了。 方法: Semaphore semaphore = new Semaphore(2);构造器,用于设置当前最大可执行的线程的个数,当前默认为非公平模式。如上例中的跑道个数...原创 2018-12-03 15:40:19 · 113 阅读 · 0 评论 -
多线程知识体系总结
点击一级类目即可跳转对应的链接1. 多线程基础概念 61.1. 进程,线程 71.1.1. 进程 71.1.2. 线程 71.2. 串行,并发,并行 71.2.1. 串行 71.2.2. 并发 71.2.3. 并行 71.3. 多核下线程数量选择 71.3.1. 计算密集型 71.3.2. IO密集型 71.4. 线程分类 71.4.1. 守护线...原创 2018-12-03 15:46:08 · 621 阅读 · 0 评论 -
26-java.util.concurrent.locks包分析
java.util.concurrent.locks包分析 类关系图 Lock接口分析 优点 tryLock():允许在一定的时间内来获取锁,获取失败则返回false,这样线程可以执行其它的操作,而不至于使线程进入休眠(synchronized获取失败则进入阻塞队列中等待)。ReentrantReadWriteLock:提供了读锁和写锁,允许多个线程获得读锁、而只...原创 2018-12-05 07:20:00 · 220 阅读 · 0 评论 -
9-Volatile-CAS-synchronized-lock对比
volatile 作用 只能保证数据的可见性,但不能保证数据的原子性,同时禁止重排序 原理 通过volatile修饰的变量只存在于JMM的主存空间中,从而保证多线程每次获取的数据均为最新的数据 使用 通常和cas结合使用,如AtomicInteger,uns...原创 2018-11-29 11:08:12 · 233 阅读 · 0 评论 -
24-常用的数据结构线程安全分析
常用的数据结构线程安全分析线程安全的数据结构:Vector,Stack,Hashtable,ConcurrentHashMap非线程安全的数据结构:ArrayList,LinkedList,ArrayQueue,HashMap,HashSet ArrayList非线程安全研究 测试代码执行结果:Exception in thread "Thread-0" java.lan...原创 2018-12-03 15:40:04 · 1193 阅读 · 0 评论 -
22-队列同步器与锁的区别联系
队列同步器与锁的区别联系如AQS队列同步器,是实现锁的关键,如定义了添加锁、释放锁的方法(final方法);而其实现类-锁,通过内部类继承AQS的方式,用于实现AQS的置空方法,实现当前锁的业务特点。而锁是针对使用者而言的,其底层是通过队列同步器实现的。 多线程学习大纲:https://mp.csdn.net/postedit/84768644 ...原创 2018-12-03 15:40:26 · 360 阅读 · 0 评论 -
21-AQS:基于FIFO等待队列的阻塞锁
AQS:基于FIFO等待队列的阻塞锁 用来做什么? 当一个线程请求一个共享资源时,如果资源处于空闲状态,则设置该线程为有效的工作线程,并设置该资源为锁定状态;当资源处于锁定状态时,需要设置其他请求的线程处于阻塞状态,并在共享资源被唤醒时,分配当前处于阻塞状态的线程使其工作。 如何实现的? 使用一个FIFO的双端队列,用于存放锁上阻塞状态的线程,同时使用voliatile in...原创 2018-12-03 15:40:32 · 913 阅读 · 0 评论 -
7-编译器/处理器的重排序
编译器/处理器的重排序 流程 原则: 编译器和处理器在重排序时,会遵守数据依赖性。不会改变存在数据依赖性关系的操作的执行顺序。 as-if-serial规则 内容:在单线程内,指令重排序后,其执行结果不能被改变。即编译器和处理器不会对存在数据依赖关系的操作做重排序 happens-before规则 目的:保证跨线程的内存可见性以及指令执行结果的不变性。...原创 2018-11-29 11:05:06 · 901 阅读 · 0 评论 -
8-DCL double-check locks(指令重排序导致的非线程安全问题)
DCL double-check locks(指令重排序导致的非线程安全问题) 单例模式1: 非线程安全模式 问题:多线程环境下,可能多个线程singleton == null,导致new多个实例对象 单例模式2:synchronized修改方法块 问题:并发比较高的情况下,速率很慢 单例模式3:DCL模式:检查-加锁-检查 instance = new Si...原创 2018-11-29 11:07:28 · 497 阅读 · 0 评论 -
10-Synchronized:悲观锁,可重入锁
Synchronized:悲观锁,可重入锁 特点:可重入的锁 可重入锁,一个获得的锁的线程没执行完可以继续获得该锁。线程占用锁的时候,如果执行的同步代码出现异常,会自动将锁让出。同步代码块的代码是同步执行的(一次执行完),而非同步代码块的代码可以异步执行。要求锁的获取和释放存在同一个块结构中;当获取了多个锁时,它们必须以相反的顺序释放; 使用注意事项:区分锁对象(锁不同没有...原创 2018-11-29 11:09:07 · 372 阅读 · 0 评论 -
11-volatile:synchronized的轻量级实现
作用:保证数据的可见性,以及确保变量不会被重排序 volatile关键字修饰的成员变量,不存在工作线程的副本;每次直接都从主内存中读取。只能保证数据的可见性,但不保证操作的原子性。 内存可见性 写一个volatile变量时,JMM首先修改工作内存中的变量值,并刷新到主内存中。读一个变量时,JMM会把该线程对应的本地内存置为无效,并从主内存中读取共享变量。对volatile...原创 2018-11-29 11:11:19 · 90 阅读 · 0 评论 -
12-CAS
CAS 什么是CAS? compare and swap。通过原子的方式,实现数据在数据符合预期的情况下,进行数据交换。 逻辑说明 多线程环境下的问题 如果线程1经判断a==b,准备执行a=c时,cpu切换到线程2,且将a改成了d,则会出现问题。 处理方案:加锁,volatile变量修饰 CAS的应用步骤 获取Unsafe的实例 初...原创 2018-11-29 11:13:19 · 83 阅读 · 0 评论 -
13-AtomicInteger中CAS-volatile的应用
AtomicInteger中CAS-volatile的应用 简介 java.util.concurrent.atomic包下,提供对整形数字的原子操作。 属性 Unsdfe:一个静态final修饰的Unsafe对象;valueOffset:在静态块中初始化获取了value的对象偏移量;Value:对象包含的真正的整形数值,由volatile关键字修饰,确保对value的修改...原创 2018-11-29 11:15:04 · 146 阅读 · 0 评论 -
14-Unsafe中CAS的应用
Unsafe中CAS的应用 实例化 位于sun.misc包中一个类,不能使用正常的new Unsafe()来创建对象,但可以通过反射去绕过限制,但最好不要使用。 compareAndSwapInt为例 var1是需要更新的变量,var2是相对object对象的偏移量(一般为var1某个整形属性的偏移量),var4是期望值,var5是整形属性的新值。 demo ...原创 2018-11-29 11:16:48 · 119 阅读 · 0 评论 -
15-线程等待通知机制总结
线程等待通知机制总结 概述 一个线程的等待阻塞状态,受另外一个线程控制。 Object.wait() Object.notify() 特点 必须基于特定的对象锁synchronized Notify只会对已经处于wait状态的线程生效。 使用 必须在synchro...原创 2018-11-29 11:18:53 · 111 阅读 · 0 评论 -
16-LockSupport源码分析
LockSupport源码分析主要用于提供阻塞线程,和解除阻塞的方法。通过UNSAFE来实现的。 属性方法总结 final long parkBlockerOffset 线程中parkBlocker属性的偏移量 可以通过该偏移地址获取或者设置该字段的值,即修改获取Thread下的parkBlocker属性值。 构造函数:私有,无法被实例化 unpark...原创 2018-12-03 15:41:24 · 151 阅读 · 0 评论 -
17-Unsafe源码分析
Unsafe源码分析 park方法 public native void park(boolean isAbsolute, long time);阻塞线程。直至unpark唤醒线程,或者设置的等待时间到达。 unpark方法 public native void unpark(Thread thread); 释放线程的许可。这个函数不是安全的,即当需要释放的线程不存活时会出...原创 2018-12-03 15:41:18 · 123 阅读 · 0 评论 -
18-Thread源码分析
Thread源码分析 volatile Object parkBlocker 属性 阻塞者,一个用来记录当前线程阻塞信息的对象。该属性只有在线程被阻塞时才有意义,没有setter/getter方法,通过unsafe.objectFieldOffset进行修改。当程序出现问题时候,通过线程监控分析工具可以找出问题所在。 parkBlocker 使用案例: 当通过jsta...原创 2018-12-03 15:40:52 · 157 阅读 · 0 评论 -
19-锁的分类
1 独占锁 一个线程获得了锁,其他线程就不能获取该锁 Synchronized是独占锁 共享锁 多个线程之间可以共享同一个锁,但是线程的数量是有限定的 Semaphore ReadWriteLock 2 可重入锁...原创 2018-12-03 15:40:43 · 90 阅读 · 0 评论 -
20-AOS
AOS 锁持有者管理器AbstractOwnableSynchronizer 作用:在独占模式下,用于设置当前同步对象的占用线程。 为什么需要将AQS持有锁的线程的标识向上抽取 AQS诞生于JDK1.5,AOS诞生于JDK1.6。而AQS并没有调用AOS中的属性和方法,AOS中的属性方法的调用是在AQS的子类中完成的。而如果直接将AOS中声明的属性或方法直接放在AQS中,对A...原创 2018-12-03 15:40:37 · 138 阅读 · 0 评论 -
31-线程局部变量 ThreadLocal
线程局部变量 ThreadLocal 原理,作用 每个Thread维护一个ThreadLocalMap 映射表,使用ThreadLocal对象为弱引用的map集合(即弱引用的对象可以在GC中被回收掉),value为对应的值。其生命周期和线程一致。作用:提供线程内的局部变量;在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。 用法 ini...原创 2018-12-11 14:26:58 · 194 阅读 · 0 评论