![](https://img-blog.csdnimg.cn/20201014180756925.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
多线程
zssz1026
这个作者很懒,什么都没留下…
展开
-
LinkedBlockingQueue的使用及其源码探秘
在并发编程中,LinkedBlockingQueue使用的非常频繁。因其可以作为生产者消费者的中间商 add 实际上调用的是offer,区别是在队列满的时候,add会报异常 offer 对列如果满了,直接入队失败 put("111"); 在队列满的时候,会进入阻塞的状态 remove(); 直接调用poll,唯一的区别即使remove会抛出异常,而poll在队列为空的时候直接返回null po...原创 2020-05-18 13:39:07 · 107 阅读 · 0 评论 -
同步容器与并发容器
同步容器 Vector、HashTable -- JDK提供的同步容器类 Collections.synchronizedXXX 本质是对相应的容器进行包装 同步容器类的缺点 在单独使用里面的方法的时候,可以保证线程安全,但是,复合操作需要额外加锁来保证线程安全 使用Iterator迭代容器或使用使用for-each遍历容器,在迭代过程中修改容器会抛出ConcurrentModificationException异常。想要避免出现ConcurrentModificationEx..原创 2020-05-18 13:38:24 · 63 阅读 · 0 评论 -
原子更新引用
AtomicReference:用于对引用的原子更新 AtomicMarkableReference:带版本戳的原子引用类型,版本戳为boolean类型。 AtomicStampedReference:带版本戳的原子引用类型,版本戳为int类型。 package com.xdclass.atomic.demo4; import java.util.concurrent.atomic.AtomicReference; public class AtomicReferenceDemo {原创 2020-05-14 15:06:41 · 322 阅读 · 0 评论 -
原子地更新属性
原子地更新某个类里的某个字段时,就需要使用原子更新字段类,Atomic包提供了以下4个类进行原子字段更新 AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference、AtomicReferenceFieldUpdater 使用上述类的时候,必须遵循以下原则 字段必须是volatile类型的,在线程之间共享变量时保证立即可见 字段的描述类型是与调用者与操作对象字...原创 2020-05-14 14:41:04 · 136 阅读 · 0 评论 -
原子更新数组类型
AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray package com.xdclass.atomic.demo2; import java.util.concurrent.atomic.AtomicIntegerArray; public class AtomicIntegerArrayDemo { public static void main(String[] args) { int[] arr = new原创 2020-05-14 14:39:07 · 221 阅读 · 0 评论 -
什么是原子类
一度认为原子是不可分割的最小单位,故原子类可以认为其操作都是不可分割 为什么要有原子类? 对多线程访问同一个变量,我们需要加锁,而锁是比较消耗性能的,JDk1.5之后, 新增的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式, 这些类同样位于JUC包下的atomic包下,发展到JDk1.8,该包下共有17个类, 囊括了原子更新基本类型、原子更新数组、原子更新属性、原子更新引用 1.8新增的原子类 DoubleAccumulator、Double..原创 2020-05-14 14:22:38 · 924 阅读 · 0 评论 -
原子更新基本类型
发展至JDk1.8,基本类型原子类有以下几个: AtomicBoolean、AtomicInteger、AtomicLong、DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder 大致可以归为3类 AtomicBoolean、AtomicInteger、AtomicLong 元老级的原子更新,方法几乎一模一样 DoubleAdder、LongAdder 对Double、Long的原子更新性能进行优化提升 DoubleAc..原创 2020-05-14 14:22:05 · 261 阅读 · 0 评论 -
Condition的使用
可以在一个锁里面,存在多种等待条件 主要的方法 await signal signalAll package com.xdclass.communication.demo6; public class Consumer implements Runnable { private Medium medium; public Consumer(Medium medium){ this.medium = medium; } @Override原创 2020-05-13 16:24:46 · 121 阅读 · 0 评论 -
ThreadLocal的使用
线程变量,是一个以ThreadLocal对象为键、任意对象为值的存储结构。为每个线程单独存放一份变量副本,也就是说一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。只要线程处于活动状态并且ThreadLocal实例可访问,那么每个线程都拥有对其本地线程副本的隐式引用变量一个线程消失后,它的所有副本线程局部实例受垃圾回收(除非其他存在对这些副本的引用) 一般用的比较多的是 ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。 ThreadLocal原创 2020-05-13 16:10:37 · 76 阅读 · 0 评论 -
Thread.join通信及其源码浅析
使用场景:线程A执行到一半,需要一个数据,这个数据需要线程B去执行修改,只有B修改完成之后,A才能继续操作 线程A的run方法里面,调用线程B的join方法,这个时候,线程A会等待线程B运行完成之后,再接着运行 package com.xdclass.communication.demo4; import static java.lang.Thread.currentThread; public class Main { public static void main(Str..原创 2020-05-13 15:38:01 · 126 阅读 · 1 评论 -
使用管道流进行通信
以内存为媒介,用于线程之间的数据传输。 主要有面向字节:【PipedOutputStream、PipedInputStream】、面向字符【PipedReader、PipedWriter】原创 2020-05-13 15:13:51 · 114 阅读 · 0 评论 -
等待通知经典模型之生产者消费者
package com.xdclass.communication.demo2; public class Consumer implements Runnable { private Medium medium; public Consumer(Medium medium){ this.medium = medium; } @Override public void run() { while (true){ .原创 2020-05-13 15:12:38 · 143 阅读 · 0 评论 -
wait、notify、notifyAll
何时使用 在多线程环境下,有时候一个线程的执行,依赖于另外一个线程的某种状态的改变,这个时候,我们就可以使用wait与notify或者notifyAll wait跟sleep的区别 wait会释放持有的锁,而sleep不会,sleep只是让线程在指定的时间内,不去抢占cpu的资源 注意点 wait notify必须放在同步代码块中, 且必须拥有当前对象的锁,即不能取得A对象的锁,而调用B对象的wait 哪个对象wait,就得调哪个对象的notify notify跟notifyAll的..原创 2020-05-13 14:31:57 · 68 阅读 · 0 评论 -
StampedLock原理及使用
.8之前,锁已经那么多了,为什么还要有StampedLock? 一般应用,都是读多写少,ReentrantReadWriteLock 因读写互斥,故读时阻塞写,因而性能上上不去。可能会使写线程饥饿 StampedLock的特点 所有获取锁的方法,都返回一个邮戳(Stamp),Stamp为0表示获取失败,其余都表示成功; 所有释放锁的方法,都需要一个邮戳(Stamp),这个Stamp必须是和成功获取锁时得到的Stamp一致; StampedLock是不可重入的;(如果一个线程已经..原创 2020-05-12 15:48:58 · 164 阅读 · 0 评论 -
读写锁特性及ReentrantReadWriteLock的使用
特性:写写互斥、读写互斥、读读共享 锁降级:写线程获取写入锁后可以获取读取锁,然后释放写入锁,这样就从写入锁变成了读取锁,从而实现锁降级的特性。 public class ReentrantReadWriteLockDemo { private int i = 0; private int j = 0; private ReadWriteLock lock = new ReentrantReadWriteLock(); Lock readLock = lock.原创 2020-05-11 14:52:29 · 123 阅读 · 0 评论 -
掌控线程执行顺序之多线程debug
详见视频原创 2020-05-11 14:29:18 · 259 阅读 · 0 评论 -
深入剖析ReentrantLock源码之公平锁的实现
公平锁与非公平锁的区别 公平锁:顾名思义--公平,大家老老实实排队 非公平锁:只要有机会,就先尝试抢占资源 公平锁与非公平锁其实有点像在公厕上厕所。公平锁遵守排队的规则,只要前面有人在排队,那么刚进来的就老老实实排队。而非公平锁就有点流氓,只要当前茅坑没人,它就占了那个茅坑,不管后面的人排了多久。 源码解析 详见视频 非公平锁的弊端 可能导致后面排队等待的线程等不到相应的cpu资源,从而引起线程饥饿 ...原创 2020-05-11 14:28:34 · 74 阅读 · 0 评论 -
深入剖析ReentrantLock源码之非公平锁的实现
如何阅读源码? 一段简单的代码 看构造 看类之间的关系,形成关系图 看使用到的方法,并逐步理解,边看代码边看注释 debug原创 2020-05-11 14:01:27 · 74 阅读 · 0 评论 -
AbstractQueuedSynchronizer浅析
AbstractQueuedSynchronizer -- 为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关同步器(信号量、事件,等等)提供一个框架。 此类的设计目标是成为依靠单个原子 int 值来表示状态的大多数同步器的一个有用基础。 子类必须定义更改此状态的受保护方法,并定义哪种状态对于此对象意味着被获取或被释放。 假定这些条件之后,此类中的其他方法就可以实现所有排队和阻塞机制。子类可以维护其他状态字段,但只是为了获得同步而只追踪使用 getState()、setState(int原创 2020-05-11 13:50:41 · 104 阅读 · 0 评论 -
实现属于自己的锁
实现lock接口 使用wait notify import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; public class MyLock implements Lock { priva...原创 2020-05-07 15:45:40 · 68 阅读 · 0 评论 -
深入理解Lock接口
Lock的使用 lock与synchronized的区别 lock 获取锁与释放锁的过程,都需要程序员手动的控制 Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就 是CAS操作 synchronized托管给jvm执行 原始采用的是CPU悲观锁机制,即线程获得的是独占锁。...原创 2020-05-07 15:16:38 · 162 阅读 · 0 评论 -
锁的分类
自旋锁: 线程状态及上下文切换消耗系统资源,当访问共享资源的时间短,频繁上下文切换不值得。jvm实现,使线程在没获得锁的时候,不被挂起,转而执行空循环,循环几次之后,如果还没能获得锁,则被挂起 阻塞锁:阻塞锁改变了线程的运行状态,让线程进入阻塞状态进行等待,当获得相应的信号(唤醒或者时间)时,才可以进入线程的准备就绪状态,转为就绪状态的所有线程,通过竞争,进入运行状态 重入锁:支持线程再次进入...原创 2020-05-07 14:56:47 · 63 阅读 · 0 评论 -
如何避免线程安全性问题
线程安全性问题成因 多线程环境 多个线程操作同一共享资源 对该共享资源进行了非原子性操作 如何避免 打破成因中三点任意一点 1:多线程环境--将多线程改单线程(必要的代码,加锁访问) 2:多个线程操作同一共享资源--不共享资源(ThreadLocal、不共享、操作无状态化、不可变) 3:对该共享资源进行了非原子性操作-- 将非原子性操作改成原子性操作(加锁、使用JDK...原创 2020-05-07 14:55:55 · 166 阅读 · 0 评论 -
单例与线程安全
饿汉式--本身线程安全 在类加载的时候,就已经进行实例化,无论之后用不用到。如果该类比较占内存,之后又没用到,就白白浪费了资源。 懒汉式 -- 最简单的写法是非线程安全的 在需要的时候再实例化 public class LazySingleton { private static volatile LazySingleton lazySingleton =...原创 2020-05-07 14:47:53 · 97 阅读 · 0 评论 -
volatile关键字及其使用场景
能且仅能修饰变量 保证该变量的可见性,volatile关键字仅仅保证可见性,并不保证原子性 禁止指令重排序 A、B两个线程同时读取volatile关键字修饰的对象,A读取之后,修改了变量的值,修改后的值,对B线程来说,是可见 使用场景 1:作为线程开关 2:单例,修饰对象实例,禁止指令重排序 ...原创 2020-05-07 14:32:32 · 122 阅读 · 0 评论 -
深入理解synchronized
内置锁 每个java对象都可以用做一个实现同步的锁,这些锁称为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁。获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。 互斥锁 内置锁是一个互斥锁,这就是意味着最多只有一个线程能够获得该锁,当线程A尝试去获得线程B持有的内置锁时,线程A必须等待或者阻塞,直到线程B释放这个锁,如果B线...原创 2020-05-07 14:32:05 · 58 阅读 · 0 评论 -
原子性操作
什么是原子性操作 一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 A想要从自己的帐户中转1000块钱到B的帐户里。那个从A开始转帐,到转帐结束的这一个过程,称之为一个事务。在这个事务里,要做如下操作: 从A的帐户中减去1000块钱。如果A的帐户原来有3000块钱,现在就变成2000块钱了。 在B的帐户里加1000块钱。如果B的帐户如果原来有...原创 2020-05-07 14:11:59 · 148 阅读 · 1 评论 -
从字节码角度剖析线程不安全操作
javac -encoding UTF-8 UnsafeThread.java 编译成.class javap -c UnsafeThread.class 进行反编译,得到相应的字节码指令 0: getstatic #2 获取指定类的静态域,并将其押入栈顶 3: iconst_1 将int型1押入栈顶 4: iadd 将栈顶两个int型相加,将结果押入栈顶 5: putstatic #2 为指...原创 2020-05-07 14:05:31 · 92 阅读 · 0 评论 -
什么是线程安全性?
当多个线程访问某个类,不管运行时环境采用何种调度方式或者这些线程如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类为线程安全的。----《并发编程实战》 什么是线程不安全? 多线程并发访问时,得不到正确的结果。 ...原创 2020-05-07 14:00:17 · 76 阅读 · 0 评论 -
守护线程
线程分类 用户线程、守护线程 守护线程:任何一个守护线程都是整个程序中所有用户线程的守护者,只要有活着的用户线程,守护线程就活着。当JVM实例中最后一个非守护线程结束时,也随JVM一起退出 守护线程的用处:jvm垃圾清理线程 建议: 尽量少使用守护线程,因其不可控不要在守护线程里去进行读写操作、执行计算逻辑 ...原创 2020-05-06 15:44:08 · 111 阅读 · 0 评论 -
线程的优先级
线程的优先级告诉程序该线程的重要程度有多大。如果有大量线程都被堵塞,都在等候运行,程序会尽可能地先运行优先级的那个线程。 但是,这并不表示优先级较低的线程不会运行。若线程的优先级较低,只不过表示它被准许运行的机会小一些而已。 线程的优先级设置可以为1-10的任一数值,Thread类中定义了三个线程优先级,分别是:MIN_PRIORITY(1)、NORM_PRIORITY(5)、MAX...原创 2020-05-06 15:43:37 · 171 阅读 · 0 评论 -
线程的中断操作
stop() 废弃方法,开发中不要使用。因为一调用,线程就立刻停止,此时有可能引发相应的线程安全性问题 Thread.interrupt方法 自行定义一个标志,用来判断是否继续执行 ...原创 2020-05-06 15:30:38 · 88 阅读 · 0 评论 -
线程的挂起跟恢复
什么是挂起线程? 线程的挂起操作实质上就是使线程进入“非可执行”状态下,在这个状态下CPU不会分给线程时间片,进入这个状态可以用来暂停一个线程的运行。 在线程挂起后,可以通过重新唤醒线程来使之恢复运行 为什么要挂起线程? cpu分配的时间片非常短、同时也非常珍贵。避免资源的浪费。 如何挂起线程? 被废弃的方法 thread.suspend() 该方法不会释放线程...原创 2020-05-06 15:30:08 · 488 阅读 · 0 评论 -
创建线程的方式
继承Thread,并重写父类的run方法 public class MyThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName()); } public static void m...原创 2020-05-06 14:56:23 · 79 阅读 · 0 评论 -
线程的状态及其相互转换
初始(NEW):新创建了一个线程对象,但还没有调用start()方法。 运行(RUNNABLE):处于可运行状态的线程正在JVM中执行,但它可能正在等待来自操作系统的其他资源,例如处理器。 阻塞(BLOCKED):线程阻塞于synchronized锁,等待获取synchronized锁的状态。 等待(WAITING):Object.wait()、join()、 LockSupport.par...原创 2020-05-06 14:41:32 · 83 阅读 · 0 评论 -
win下查看线程命令
在DOS窗口输入jps E:\idea_workspace\xd\concurrent>jps 22548 RemoteMavenServer 21624 Launcher 22952 DeadLockDemo 19964 Jps 21964 jstack 22952 打开JAVA监视和管理控制台:jconsole 选择线程 ...原创 2020-03-03 15:52:01 · 969 阅读 · 0 评论