![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
多线程
一笑而过者也
爱好java,分布式开发
展开
-
FutureTask源码解析
Future设计模式属性 private volatile int state; //当前任务状态 private static final int NEW = 0; //定义的状态常量 private static final int COMPLETING = 1; private static final int NORMAL = 2; private static final int EXCEPTIONAL = 3;原创 2021-03-10 22:54:43 · 136 阅读 · 0 评论 -
java volatile关键字
前言: volatile用在并发编程中,主要用来解决缓存一致性。1.内存模型 程序在执行时,临时数据都是放入内存中的,cpu执行很快,要比在内存中取数据,写数据快很多,所以cpu里面有了高速缓存,实际程序在执行时,先将数据从内存复制到cpu告诉缓存中,cpu在执行过程中,就在高速缓存cache中读取和写入数据,然后再刷新到主存中。在高并发情况下,就会出...原创 2018-08-12 10:42:54 · 128 阅读 · 0 评论 -
CountDownLatch源码解析
1. 首先看一下CountDownLatch的构造函数 public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count); }然后看一下Sync类,...原创 2020-03-07 21:11:21 · 166 阅读 · 0 评论 -
CyclicBarrier源码解析
1. 先看一下构造函数public CyclicBarrier(int parties, Runnable barrierAction) { if (parties <= 0) throw new IllegalArgumentException(); this.parties = parties; this.count = parties; this.ba...原创 2020-03-07 22:28:31 · 170 阅读 · 0 评论 -
Semaphore源码解析
1. 构造函数 public Semaphore(int permits) { sync = new NonfairSync(permits); } public Semaphore(int permits, boolean fair) { sync = fair ? new FairSync(permits) : new NonfairS...原创 2020-03-08 16:37:36 · 146 阅读 · 0 评论 -
Executors
1. 介绍线程池工厂,在实际生产环境中,线程的数量必须得到控制,盲目的大量创建线程对系统性能是有伤害的。2. 主要方法2.1 newFixedThreadPool() 该方法返回一个固定线程数量的线程池,该线程池中的线程数量始终不变,当有一个新的任务提交时,线程池中若有空闲线程,则立即执行,若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。线程数固定...原创 2020-02-07 12:28:17 · 518 阅读 · 0 评论 -
阻塞队列介绍
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。1)支持阻塞的插入方法:意思是当队列满时,队列会阻塞插入元素的线程,直到队列不满。2)支持阻塞的移除方法:意思是在队列为空时,获取元素的线程会等待队列变为非空。阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。阻塞队列就是生产者用来存放...原创 2020-02-07 12:10:55 · 224 阅读 · 0 评论 -
CyclicBarrier
1. 介绍 它可以实现线程间的计数等待,并且可以循环计数。每凑齐一批后又可以继续重新计数。2. 构造函数public CyclicBarrier(int parties);public CyclicBarrier(int parties, Runnable barrierAction);3. 示例集合完毕会执行回调方法,任务完成也会再执行一个回调方法。public class T...原创 2020-02-07 11:32:21 · 146 阅读 · 0 评论 -
CountDownLatch
1. 介绍通常用来控制线程的等待,可以理解为一个倒计数工具。它可以让一个线程等待直到倒计数结束,再开始执行。计数只能减,不能增。2. 构造函数public CountDownLatch(int count);接收一个整数作为参数,即当前计数器的计数个数3. 案例主线程在CountDownLatch上等待,所有任务完成后,主线程方能继续执行。public class Test01 {...原创 2020-02-07 11:22:32 · 104 阅读 · 0 评论 -
Semaphore
1.介绍信号量为多线程协作提供了更为强大的控制方法。广义上说信号量是对锁的扩展,可以指定多个线程同时访问某一资源。2. 构造方法 public Semaphore(int permits) { sync = new NonfairSync(permits); } public Semaphore(int permits, boolean fair) ...原创 2020-02-07 11:17:48 · 95 阅读 · 0 评论 -
CAS原理
compareAndSet()方法调用简称为CAS。JDK文档对该方法的说明如下:如果当前状态值等于预期值,则以原子方式将同步状态设置为给定的更新值。此操作具有volatile读和写的内存语义。 编译器不会对volatile读与volatile读后面的任意内存操作重排序;编译器不会对volatile写与volatile写前面的任意内存操作重排序。组合这两个条件,意味着为了同时实现volat...原创 2020-02-07 11:09:27 · 131 阅读 · 0 评论 -
LockSupport示例
1. 介绍LockSupport是一个非常方便实用的线程阻塞工具,它可以在线程内任意位置阻塞线程。和Thread.suspend()相比,它弥补了由于resume()发生在前,导致线程无法继续执行的情况。和Object.wait()相比,它不需要先获得某个对象的锁,也不会抛出InterruptedException异常。2. 主要方法都是静态方法public static void par...原创 2020-02-06 23:01:29 · 242 阅读 · 0 评论 -
LockSupport
当需要阻塞或唤醒一个线程的时候,都会使用LockSupport工具类来完成相应工作。LockSupport定义了一组的公共静态方法,这些方法提供了最基本的线程阻塞和唤醒功能,而LockSupport也成为构建同步组件的基础工具。 在Java 6中,LockSupport增加了park(Object blocker)、parkNanos(Object blocker,long nanos)...原创 2020-02-06 22:53:04 · 126 阅读 · 0 评论 -
独占式超时获取同步状态
通过调用同步器的doAcquireNanos(int arg,long nanosTimeout)方法可以超时获取同步状态,即在指定的时间段内获取同步状态,如果获取到同步状态则返回true,否则,返回false。超时获取同步状态过程可以被视作响应中断获取同步状态过程的“增强版”,doAcquireNanos(int arg,long nanosTimeout)方法在支持响应中断的基础上,增加了...原创 2020-02-06 22:28:24 · 252 阅读 · 0 评论 -
共享式同步状态获取与释放
共享式获取与独占式获取最主要的区别在于同一时刻能否有多个线程同时获取到同步状态public final void acquireShared(int arg) { if (tryAcquireShared(arg) < 0) doAcquireShared(arg);} 在acquireShared(int arg)方法中,同步器调用tryAcquireSh...原创 2020-02-06 22:24:00 · 134 阅读 · 0 评论 -
独占式同步状态获取与释放
通过调用同步器的acquire(int arg)方法可以获取同步状态,该方法对中断不敏感public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfI...原创 2020-02-06 22:15:00 · 235 阅读 · 0 评论 -
AQS之同步队列
同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成为一个节点(Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点中的线程唤醒,使其再次尝试获取同步状态设置尾节点 同步队列遵循FIFO,首节点是获取同步状态成功的节点,首节点的线程在释放同步状态时,将会唤醒后继节点,而后...原创 2020-02-06 21:47:21 · 855 阅读 · 0 评论 -
AQS应用方式
同步器的设计是基于模板方法模式的,也就是说,使用者需要继承同步器并重写指定的方法,随后将同步器组合在自定义同步组件的实现中,并调用同步器提供的模板方法,而这些模板方法将会调用使用者重写的方法。重写同步器指定的方法时,需要使用同步器提供的如下3个方法来访问或修改同步状态。getState():获取当前同步状态。setState(int newState):设置当前同步状态。compar...原创 2020-02-06 21:37:10 · 257 阅读 · 0 评论 -
AQS简介
队列同步器AbstractQueuedSynchronizer(以下简称同步器),是用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作,并发包的作者(Doug Lea)期望它能够成为实现大部分同步需求的基础。 同步器的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态,在抽象方法的实现过程...原创 2020-02-06 21:34:50 · 120 阅读 · 0 评论 -
ReadWriteLock
1. 介绍ReadWriteLock是jdk5中提供的读写分离锁,读写分离锁可以有效的帮助减少锁竞争,以提升系统性能。读-读 不互斥读-写 互斥,写阻塞读,读也阻塞写写-写 互斥维护了一对锁 - 读锁与写锁公平性重入性锁降级 – 写锁可降级为读锁不支持锁升级2. 设计将变量切分成了两部分,高16位标识读,低16位标识写。...原创 2020-02-06 21:09:20 · 118 阅读 · 0 评论 -
Condition实现分析
ConditionObject是同步器AbstractQueuedSynchronizer的内部类,因为Condition的操作需要获取相关联的锁,所以作为同步器的内部类也较为合理。每个Condition对象都包含着一个队列(以下称为等待队列),该队列是Condition对象实现等待/通知功能的关键。1. 等待队列 等待队列是一个FIFO的队列,在队列中的每个节点都包含了一个线程...原创 2020-02-06 20:56:07 · 136 阅读 · 0 评论 -
ThreadLocal中的WeakReference
Thread对象有一个变量名为threadLocals的ThreadLocalMap对象,里面定义了一个Entry数组,Entry对象弱引用了ThreadLocal。private void set(ThreadLocal<?> key, Object value) { // We don't use a fast path as with get(...原创 2020-02-06 20:48:47 · 615 阅读 · 0 评论 -
双重检查几种方案
有时候需要采用延迟初始化来降低初始化类和创建对象的开销。双重检查锁定是常见的延迟初始化技术,但它是一个错误的用法。 在Java程序中,有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化。此时,程序员可能会采用延迟初始化。synchronized将导致性能开销public class SafeLazyInitialization { private...原创 2020-02-06 20:38:42 · 749 阅读 · 0 评论 -
锁的升级
Java SE 1.6为了减少获得锁和释放锁带来的性能消耗,引入了“偏向锁”和“轻量级锁”,在Java SE 1.6中,锁一共有4种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态,这几个状态会随着竞争情况逐渐升级。目的是为了提高获得锁和释放锁的效率1. 偏向锁 HotSpot 的作者经过研究发现,大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为...原创 2020-02-06 20:37:06 · 106 阅读 · 0 评论 -
volatile的内存语义
volatile的特征 理解volatile特征的一个好的办法是把volatile变量的单个读/写,看成是使用同一个锁对这些单个读/写做了同步。锁的happens-before规则保证释放锁和获取锁两个线程之间的内存可见性,这意味着对一个volatile变量的读总能看到任意线程对这个volatile变量最后的写入。 锁的内存语义决定了临界区代码的执行具有原子性,如果是多个volatile操...原创 2020-02-06 20:33:07 · 187 阅读 · 0 评论 -
Java如何实现原子操作
在Java中可以通过锁和循环CAS的方式来实现原子操作。(1)使用循环CAS实现原子操作 JVM中的CAS操作正是利用了处理器提供的CMPXCHG指令实现的。自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止。(2)使用锁机制实现原子操作 锁机制保证了只有获得锁的线程才能够操作锁定的内存区域。JVM内部实现了很多种锁机制,有偏向锁、轻量级锁和互斥锁。有意思的是除了偏向锁,JVM...原创 2020-02-06 20:31:10 · 905 阅读 · 0 评论 -
原子操作实现原理
原子(atomic)本意是“不能被进一步分割的最小粒子”,而原子操作(atomic operation)意为“不可被中断的一个或一系列操作”。如何实现原子操作(1)使用总线锁保证原子性 总线锁就是使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,那么该处理器可以独占共享内存。(2)使用缓存锁保证原子性 在同一时刻,我们只需保证对某个...原创 2020-02-06 20:28:14 · 256 阅读 · 0 评论 -
重排序
在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排序。重排序分3种类型。1)编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。2)指令级并行的重排。现代处理器采用了指令级并行技术(Instruction-Level Parallelism,ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。3)内存系统的...原创 2020-02-06 20:23:27 · 325 阅读 · 0 评论 -
Java内存模型的概念
1. 并发编程模型的两个关键问题 在并发编程中,需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体) 通信是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递。在共享内存的并发模型里,线程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐式通信。在消息传递的并发模型里,线程之间没有公共状态,线程之间必须...原创 2020-02-06 20:21:48 · 107 阅读 · 1 评论 -
09Condition
Condition是与重入锁相关联的,通过Lock接口的Condition newCondition()方法生成一个与当前重入锁绑定的Condition实例。利用Condition对象,我们就可以让线程在合适的时间等待,或者在某一特定的时刻得到通知,继续执行。1. Condition接口提供的方法void await() throws InterruptedException;void a...原创 2019-12-04 23:14:35 · 122 阅读 · 0 评论 -
08ReentrantLock
重入锁,手动加锁和释放锁,退出临界区时必须手动释放,否则其它线程无法访问资源了。主要有一下几个特性:1. 可重入同一线程可以多次获得锁,但是在释放锁时,也要释放相同的次数,如果释放次数多,会得到一个IllegalMonitorStateException异常,如果释放次数少,相当于还持有锁。public class Test01 { public static class Loc...原创 2019-12-04 23:13:41 · 121 阅读 · 0 评论 -
07volatile的定义与实现原理
只能保证有序性和可见性,不能保证原子性实时内容请关注微信公众号,公众号与博客同时更新:程序员星星原创 2019-12-02 23:37:14 · 158 阅读 · 0 评论 -
06synchronized
synchronized的作用是实现线程间同步,它的工作是对同步代码块加锁,使得每一次只能有一个线程进入同步块,从而保证线程间安全性。synchronized有三种用法:指定加锁对象:对给定的对象加锁,进入同步代码块前要获得给定对象的锁。直接作用于实例方法:相当于对当前实例加锁,进入同步代码块前要获得当前实例的锁。直接作用于静态方法:相当于对当前类加锁,进入同步代码块前要获得当前类的锁...原创 2019-12-02 23:35:55 · 112 阅读 · 0 评论 -
05Thread类方法解析
Thread类方法解析介绍class Thread implements Runnable,Thread类继承Runnable,重写了run方法1. 构造方法Thread(Runnable target)接收一个Runnable类型的对象,赋值给Thread类属性private Runnable target;2. start()/run()start()是开启一个线程执行run()方...原创 2019-11-28 23:57:42 · 213 阅读 · 0 评论 -
04创建线程的几种方式
创建线程的几种方式1. 继承Threadpublic class Test01Thread { @Test public void test02() throws Exception{ System.out.println("主线程开始..."); ThreadDemo01 demo01 = new ThreadDemo01();// ...原创 2019-11-28 23:56:36 · 118 阅读 · 0 评论 -
03happen-before原则
程序顺序性原则:一个线程内保证语义串行性volatile原则:volatile变量的写,先发生于读,这保证了volatile变量的可见性锁规则:解锁(unlock)必然发生于随后的加锁(lock)前传递性:A先于B,B先于C,那么A必然先于C线程start()方法先于它的每一个动作线程的所有操作先于线程的终结(Thread.join())线程的中断(interrupt())先于被中断...原创 2019-11-28 23:55:13 · 154 阅读 · 0 评论 -
00进程与线程
进程(process):是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。线程(thread): 是程序执行的最小单位,线程的状态:public enum State{ NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED}NEW表示刚刚创建的线程,这种线程...原创 2019-11-27 23:17:42 · 110 阅读 · 0 评论 -
02java内存模型JMM
java内存模型JMM线程安全的几个概念1. 原子性(atomicity) 一个操作,不可分割,要么完成,要么失败。比如:int i = 0是原子性操作,而i=i+1不是原子性操作,因为需要先计算i+1,然后再赋值给i,如果多个线程同时操作,最终i的值是不确定的。2. 可见性(visibility) 多线程操作共享数据时,每个线程会把值读入自己的线程内存中,如果有线程修改了值,也可能...原创 2019-11-27 22:20:40 · 105 阅读 · 0 评论 -
01线程的基本概念
1. 同步(synchronize)同步可以理解为:程序按照代码的顺序从头执行到尾,必须等待执行完这行代码才能执行下面的代码。2. 异步(asynchronize)异步可以理解为:程序在执行过程中开启了多个线程,不必非要等待这行代码执行完才可以执行下一行代码,不同线程的代码是可以同时执行的。3. 并发(concurrency)多个任务看上去同时执行,其实是cpu分配一段时间给这个线程,...原创 2019-11-27 21:56:08 · 110 阅读 · 0 评论