![](https://img-blog.csdnimg.cn/20201014180756913.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
JUC并发编程
文章平均质量分 91
一个风轻云淡
先搞钱,去养老,当保安,过日子(本人菜鸡一个,又菜又爱敲,希望能和您共同进步,当然如果您有问题,我会的,会尽量及时解答)
展开
-
JDK 7 ConcurrentHashMap
JDK1.7中的ConcurrentHashMap间接地实现了Map,并将每一个元素称为分段锁segment,每个segment都是一个HashEntry数组,称为table,table的每个元素都是一个HashEntry的单向队列。「HashTable是给整个容器加锁,ConcurrentHashMap是给每个segment加锁,」原创 2023-07-14 09:06:48 · 437 阅读 · 0 评论 -
JDK 8 ConcurrentHashMap
数组(Node) +( 链表 Node | 红黑树 TreeNode ) 以下数组简称(table),链表简称(bin) 初始化,使用 cas 来保证并发安全,懒惰初始化 table树化,当 table.length < 64 时,先尝试扩容,超过 64 时,并且 bin.length > 8 时,会将链表树化,树化过程 会用 synchronized 锁住链表头put,如果该 bin 尚未创建,只需要使用 cas 创建 bin;原创 2023-07-13 09:54:34 · 555 阅读 · 0 评论 -
JDK 7 HashMap 并发死链
这是为了观察 e 节点和 next 节点的状态,Thread-0 单步执行到 594 行,再 594 处再添加一个断点(条件Thread.currentThread().getName().equals("Thread-0")) 这时可以在 Variables 面板观察到 e 和 next 变量,使用 view as -> Object 查看节点状态。第二次循环,注意这时 e 是 (35,1) 并链向 (1,null) 所以 next 又是 (1,null) [1] (35,1)->(1,null)原创 2023-07-12 10:58:26 · 286 阅读 · 0 评论 -
volatile 原理
volatile 的底层实现原理是内存屏障,Memory Barrier(Memory Fence)原创 2023-07-10 16:07:50 · 404 阅读 · 0 评论 -
Semaphore使用及原理解读
Semaphore(信号量)是Java中一个并发控制工具,用于控制对共享资源的访问。它基于计数器的原理,可以限制同时访问某个资源的线程数量。在Java中使用Semaphore,你需要按照以下步骤进行操作:导包:其中,n是允许同时访问共享资源的线程数量。try {// 获取信号量,如果没有可用的许可证,线程将被阻塞// 访问共享资源的代码// 处理中断异常// 释放信号量,增加一个许可证acquire()原创 2023-07-11 08:10:16 · 3053 阅读 · 0 评论 -
Fork/Join解读
任务会被分发给空闲的工作线程执行,如果一个线程的工作队列为空,它可以从其他线程的队列中窃取任务来执行。提交给 Fork/Join 线程池的任务需要继承 RecursiveTask(有返回值)或 RecursiveAction(没有返回值),例如下 面定义了一个对 1~n 之间的整数求和的任务。所谓的任务拆分,是将一个大任务拆分为算法上相同的小任务,直至不能拆分可以直接求解。Fork/Join 是 JDK 1.7 加入的新的线程池实现,它体现的是一种分治思想,适用于能够进行任务拆分的 cpu 密集型 运算。原创 2023-06-29 09:02:23 · 520 阅读 · 0 评论 -
读写锁原理解读
读写锁是一对互斥锁,分为读锁和写锁。读锁和写锁互斥,让一个线程在进行读操作时,不允许其他线程的写操作,但是不影响其他线程的读操作;当一个线程在进行写操作时,不允许任何线程进行读操作或者写操作。读写锁用的是同一个 Sycn 同步器,因此等待队列、state 等也是同一个。原创 2023-06-27 08:14:34 · 2731 阅读 · 0 评论 -
非公平锁实现原理+源码解读
当前队列不为 null,并且 head 的 waitStatus = -1,进入 unparkSuccessor 流程 找到队列中离 head 最近的一个 Node(没取消的),unpark 恢复其运行,本例中即为 Thread-1。Thread-1 再次进入 acquireQueued 流程,获取锁失败,重新进入 park 阻塞。2. 进入 tryAcquire 逻辑,这时 state 已经是1,结果仍然失败。如果这时候有其它线程来竞争(非公平的体现),例如这时有 Thread-4 来了。原创 2023-06-25 09:50:39 · 230 阅读 · 0 评论 -
可重入,可打断,公平锁,条件变量原理解读
加锁时:compareAndSetState,尝试改变状态,成功就把Owner设置为当前线程,失败就再tryAcquire一次,还是失败,就创建一个节点对象,把线程加到等待队列(双向链表)里面去,park住当前线程;释放锁:两种情况,一是唤醒的时候没有加锁的来竞争,唤醒head的后继结点,unpark它,然后把head节点链接到next等待的线程;当线程请求一个由其它线程持有的对象锁时,该线程会阻塞,而当线程请求由自己持有的对象锁时,如果该锁是重入锁,请求就会成功,否则阻塞。原创 2023-06-26 09:34:46 · 234 阅读 · 0 评论 -
AQS 原理解读
全称是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架特点: 用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取 锁和释放锁getState - 获取 state 状态setState - 设置 state 状态compareAndSetState - cas 机制设置 state 状态。原创 2023-06-28 07:54:58 · 294 阅读 · 0 评论 -
Tomcat 线程池
Tomcat 是一个流行的 Java Web 服务器,它使用线程池来处理客户端请求。线程池是一组预先创建的线程,用于执行并发任务,以提高性能和资源利用率。在 Tomcat 中,线程池被用来处理传入的 HTTP 请求。当客户端发送请求时,Tomcat 会从线程池中获取一个可用的线程来处理该请求。处理完请求后,线程将返回线程池,并在下一个请求到来时再次被重用。Tomcat 的线程池配置可以通过编辑server.xml文件来进行。maxThreads:指定线程池中的最大线程数。原创 2023-07-09 06:36:38 · 3409 阅读 · 3 评论 -
任务调度线程池
功能加入之前,可以使用 java.util.Timer 来实现定时功能,Timer 的优点在于简单易用,但 由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,输出分析:一开始,延时 1s,scheduleWithFixedDelay 的间隔是 上一个任务结束 -> 延时 -> 下一个任务开始 所 以间隔都是 3s。输出分析:一开始,延时 1s,接下来,由于任务执行时间 > 间隔时间,间隔被『撑』到了 2s。同一时间只能有一个任务在执行,前一个 任务的延迟或异常都将会影响到之后的任务。原创 2023-06-24 09:41:37 · 219 阅读 · 0 评论 -
异步模式之工作线程
让有限的工作线程(Worker Thread)来轮流异步处理无限多的任务。也可以将其归类为分工模式,它的典型实现 就是线程池,也体现了经典设计模式中的享元模式。例如,海底捞的服务员(线程),轮流处理每位客人的点餐(任务),如果为每位客人都配一名专属的服务员,那 么成本就太高了(对比另一种多线程设计模式:Thread-Per-Message)注意,不同任务类型应该使用不同的线程池,这样能够避免饥饿,并能提升效率。原创 2023-06-23 10:15:55 · 601 阅读 · 1 评论 -
ThreadPoolExecutor解读
评价 整个线程池表现为线程数会根据任务量不断增长,没有上限,当任务执行完毕,空闲 1分钟后释放线 程。当线程数达到 corePoolSize 并没有线程空闲,这时再加入任务,新加的任务会被加入workQueue 队列排 队,直到有空闲的线程。核心线程数是 0, 最大线程数是 Integer.MAX_VALUE,救急线程的空闲生存时间是 60s,意味着。线程池中刚开始没有线程,当一个任务提交给线程池后,线程池会创建一个新线程来执行任务。来了五个任务,核心线程为2,最大线程为3,阻塞队列大小为2。原创 2023-06-22 09:42:13 · 253 阅读 · 0 评论 -
同步模式之保护性暂停
即 Guarded Suspension,用在一个线程等待另一个线程的执行结果要点有一个结果需要从一个线程传递到另一个线程,让他们关联同一个 GuardedObject如果有结果不断从一个线程到另一个线程那么可以使用消息队列(见生产者/消费者)JDK 中,join 的实现、Future 的实现,采用的就是此模式因为要等待另一方的结果,因此归类到同步模式保护性暂停(Guarded Suspension)是一种线程间的同步机制,它解决了等待-通知模式中的等待超时和虚假唤醒问题。原创 2023-06-19 09:52:46 · 332 阅读 · 0 评论 -
JUC之可见性和有序性
具体地,如果操作A happens-before操作B,那么我们可以保证看到操作A的线程对共享变量的修改对操作B的线程是可见的。Happens-before原则是Java内存模型中的一个概念,它定义了在并发情况下,对共享变量的写操作和读操作之间的可见性关系,包括线程启动、线程终止、同步块、volatile变量等多种场景,确保了多个线程之间的操作顺序。在JMM中,并不保证一个线程修改变量后,另一个线程能够立即看到这个变化,这是因为每个线程都有自己的工作内存,线程之间不能直接读写彼此的工作内存。原创 2023-06-17 08:49:27 · 581 阅读 · 0 评论 -
共享模型之不可变
这是因为,当一个线程将final变量的值写入主内存后,其他线程读取该变量时,会从主内存加载该变量的值,而不是从自己线程内部的缓存中加载,从而保证了线程之间final变量值的可见性。因为final变量的值已经确定,Java虚拟机在读取final变量的值时,会直接从常量池中读取,而不是从堆内存中读取。这种优化方式的好处在于可以加快程序的执行速度,同时也可以避免线程安全问题,因为final变量的值不可修改,也不需要进行同步处理。不可变对象,实际是另一种避免竞争的方式。日 期 转 换 的 问 题。原创 2023-06-16 07:48:18 · 209 阅读 · 0 评论 -
变量的线程安全分析
具体来说,在Java中,String类的任何方法都是线程安全的,因为String类对象本身是不可变的,即String类的实例字段都声明为final类型,这些实例字段的值一旦被初始化后便无法更改,同时这些实例字段也没有提供任何可以修改它们的方法。String、Integer 等都是不可变类,因为其内部的状态不可以改变,因此它们的方法都是线程安全的 有同学或许有疑问,String 有 replace,substring 等方法【可以】改变值啊,那么这些方法又是如何保证线程安 全的呢?分析下面代码是否线程安全?原创 2023-06-15 07:51:59 · 263 阅读 · 0 评论 -
一文打通CAS
CAS(compare and swap)的缩写,中文翻译成比较并交换,实现并发算法时常用到的一种技术。它包含三个操作数——内存位置、预期原值及更新值。执行CAS操作的时候,将内存位置的值与预期原值比较:如果相匹配,那么处理器会自动将该位置值更新为新值,如果不匹配,处理器不做任何操作,多个线程同时执行CAS操作只有一个会成功。原创 2023-04-15 07:21:19 · 262 阅读 · 0 评论 -
一文打通锁升级(偏向锁,轻量级锁,重量级锁)
在JavaSE1.6以前,synchronized都被称为重量级锁。但是在JavaSE1.6的时候,对synchronized进行了优化,引入了偏向锁和轻量级锁,以及锁的存储结构和升级过程,减少了获取锁和释放锁的性能消耗,有些情况下它也就不那么重了。如果锁获取失败,则偏向锁升级为轻量级锁(设置偏向锁标识为0并设置锁标志位为00),此时轻量级锁由原持有偏向锁的线程持有,继续执行其同步代码,而正在竞争的线程B会进入自旋等待获得该轻量级锁。原创 2023-04-14 07:46:45 · 809 阅读 · 0 评论 -
集合的线程安全解读
首先我们对 CopyOnWriteArrayList 进行学习,其特点如下: 它相当于线程安全的 ArrayList。和 ArrayList 一样,它是个可变数组;原创 2023-04-10 08:38:24 · 372 阅读 · 0 评论 -
原子操作类解读
Java中提供了一些原子操作类,用于实现多线程环境下的数据同步问题。其中最常见的有以下几种:1. AtomicBoolean:原子操作布尔型变量。2. AtomicInteger:原子操作整型变量。3. AtomicLong:原子操作长整型变量。4. AtomicReference:原子操作引用类型变量。5. AtomicStampedReference:原子操作带有版本号的引用类型变量。原创 2023-04-08 08:19:03 · 472 阅读 · 0 评论 -
一文打通JMM(Java内存模型)
JMM(Java内存模型Java Memory Model,简称JMM)本身是一种抽象的概念并不真实存在它仅仅描述的是一组约定或规范,通过这组规范定义了程序中(尤其是多线程)各个变量的读写访问方式并决定一个线程对共享变量的写入以及如何变成对另一个线程可见,关键技术点都是围绕多线程的原子性、可见性和有序性展开的。原则:它规定了在多线程环境下,不同线程之间共享的变量的可见性、有序性和原子性,以及线程之间的交流方式和对共享资源的访问规则。JMM原则对于保证多线程程序的正确性和性能有着重要的作用。能干嘛?原创 2023-04-03 07:42:33 · 209 阅读 · 0 评论 -
volatile解读
被volatile修饰的变量对于所有线程都是可见的,即当一个线程修改volatile变量的值后,其他线程立即可见修改后的值。写完后立即刷新回主内存并及时发出通知,大家可以去主内存拿最新版,前面的修改对后面所有线程可见,原创 2023-04-02 09:11:12 · 787 阅读 · 0 评论 -
一文速通JUC中的各种锁
一文带你打通乐观锁和悲观锁、公平锁和非公平锁、递归锁(可重入锁)、死锁及排查、自旋锁原创 2023-03-31 07:45:20 · 555 阅读 · 1 评论 -
JUC之阻塞队列解读(BlockingQueue)
Concurrent 包中,BlockingQueue 很好的解决了多线程中,如何高效安全 “传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建 高质量的多线程程序带来极大的便利。本文详细介绍了 BlockingQueue 家庭中的所有成员,包括他们各自的功能以及常见使用场景。阻塞队列,顾名思义,首先它是一个队列, 通过一个共享的队列,可以使得数据 由队列的一端输入,从另外一端输出;当队列是空的,从队列中获取元素的操作将会被阻塞当队列是满的,从队列中添加元素的操作将会被阻塞。原创 2023-03-30 07:16:54 · 460 阅读 · 0 评论 -
java读写锁解读
现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那 么频繁。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以 应该允许多个线程同时读取共享资源;但是如果一个线程想去写这些共享资源, 就不应该允许其他线程对该资源进行读和写的操作了。针对这种场景,JAVA 的并发包提供了读写锁 ReentrantReadWriteLock, 它表示两个锁,一个是读操作相关的锁,称为共享锁;一个是写相关的锁,称为排他锁1. 线程进入读锁的前提条件:• 没有其他线程的写锁。原创 2023-04-06 07:47:17 · 496 阅读 · 0 评论 -
JUC 三大辅助类解读
UC 中提供了三种常用的辅助类,通过这些辅助类可以很好的解决线程数量过 多时 Lock 锁的频繁操作。这三种辅助类为:CountDownLatch: 减少计数CyclicBarrier: 循环栅栏Semaphore: 信号灯原创 2023-03-29 07:31:28 · 279 阅读 · 0 评论 -
JUC之线程中断机制解读(interrupt)
①如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已。被设置中断标志的线程将继续正常运行,不受影响。所以,interrupt()并不能真正的中断线程,需要被调用的线程自己进行配合才行。②如果线程处于被阻塞状态(例如处于sleep, wait, join等状态),在别的线程中调用当前线程对象的interrupt方法,那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。在catch块中应该加上一行代码:Thread.currentThread().原创 2023-03-27 08:35:25 · 379 阅读 · 0 评论 -
Lock 接口解读
Lock 锁实现提供了比使用同步方法和语句可以获得的更广泛的锁操作。它们允 许更灵活的结构,可能具有非常不同的属性,并且可能支持多个关联的条件对 象。Lock 提供了比 synchronized 更多的功能。Lock 不是 Java 语言内置的,synchronized 是 Java 语言的关键字,因此是内置特性。Lock 是一个类,通过这个类可以实现同步访问;原创 2023-03-23 07:33:10 · 423 阅读 · 1 评论 -
JUC是什么?
在 Java 中,线程部分是一个重点,本篇文章说的 JUC 也是关于线程的。JUC 就是 java.util .concurrent 工具包的简称。这是一个处理线程的工具包,JDK 1.5 开始出现的。原创 2023-03-21 07:40:19 · 229 阅读 · 0 评论