多线程
文章平均质量分 81
多线程那点事
爱琴孩
扫盲+科普+解惑,愿天下程序员每天少掉头发
展开
-
java实现锁的几种方式
在 Java 中,除了对象锁,还有显示的加锁的方式,比如 Lock 接口,用得比较多的就是 ReentrantLock。它的特性如下:下面我们再来对比看下 ReentrantLock 和 synchronized 的区别从这些对比就能看出 ReentrantLock 使用更加的灵活,特性更加丰富。ReentrantLock 是一个悲观锁,即是同一个时刻,只允许一个线程访问代码块,这一点 synchronized 其实也一样。转载 2024-09-21 19:14:38 · 99 阅读 · 0 评论 -
ReadWriteLock提升性能的终极指南
1.1 什么是ReadWriteLock在并发编程中,ReadWriteLock是一个锁,它允许多个线程同时读共享数据,而写操作则是互斥的。这意味着如果没有线程正在对数据进行写入,那么多个线程可以同时进行读取操作,从而提高程序的性能和吞吐量。1.2 ReadWriteLock与其他锁的比较相比于传统的互斥锁,ReadWriteLock在处理读多写少的场景时更加高效,因为它允许多个读操作并发执行,而不是让所有读写操作都串行化,因为缓存的读取操作往往比写入操作要多得多。1.3 使用场景与优势。转载 2024-08-28 22:32:39 · 35 阅读 · 1 评论 -
多线程优化的坑
但好景不长,随着流量的增加,接口响应时间也在逐渐变长,p99 超过 5 秒,最后系统抛出大量的。系统恢复后,小艾仔细查看系统监控,CPU使用率并不高,内存也处于正常水位,接口性能居然比优化前还差,真心不知道哪里出了问题。当我们在处理慢接口问题时,经常会使用多线程技术,将能够并行处理的任务拆分到不同的线程中处理,等任务处理完成后,再收集各线程的处理结果,进行后续的处理。上面提到一个小问题,在资源充足情况下,所有任务均有线程池线程完成,主线程一致处于等待状态,存在一定的资源浪费。,从而触发接口异常。转载 2024-01-27 22:14:13 · 49 阅读 · 0 评论 -
AQS独占模式获取锁
采用虚节点当头结点,主要是因为每个节点都需要设置前置节点的 ws 状态(这个状态是为了保证数据一致性),如果只有一个线程竞争锁时,只有一个结点,其是没有前置节点的,所以需要创建一个虚拟节点,这样就能兼容临界情况当只有一个线程竞争锁时,无需初始化生成同步队列,直接获取同步锁即可。hasQueuedPredecessors源码很简短,就是判断有没有别的线程排在了当前线程的前面,如果有的话,返回true表示线程需要排队,没有则返回false则表示线程无需排队,也就是为公平锁判断线程需不需要排队。转载 2023-10-06 10:17:30 · 46 阅读 · 0 评论 -
AQS简介
AbstractQueuedSynchronizer,一般简称,也叫AbstractQueuedSynchronizer是Java并发工具包的,它是一个同步框架,为Java的各种同步器,锁等提供了并发抽象,是由大名鼎鼎的完成。转载 2023-10-05 20:21:07 · 49 阅读 · 0 评论 -
ReentrantLock源码解析
当我们去阅读ReentrantLock的源码时,发现有以下3个类:其中:ReentrantLock类内部总共存在Sync、NonfairSync、FairSync三个类,NonfairSync与FairSync类继承自Sync类,Sync类继承自AbstractQueuedSynchronizer抽象类,当然ReentrantLock类本身继承Lock接口。转载 2023-10-05 17:33:30 · 42 阅读 · 0 评论 -
AQS之可重入锁和非可重入锁
顾名思义叫,是指当在获取外层同步方法锁的时候,再进入该线程的内层同步方法会自动获取锁,其实就是,并不会因为之前已经获取过还没释放而阻塞,这样就,这个叫。与本文的都属于可重入锁。转载 2023-10-05 17:13:47 · 107 阅读 · 0 评论 -
AQS之公平锁和非公平锁
缺点:吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞,线程 每次从阻塞恢复到运行状态 都需要从用户态转换成内核态,而这个状态的转换是比较慢的,因此公平锁的执行速度会比较慢,而且CPU唤醒阻塞线程的开销会很大。非公平锁,其优点:不遵守先到先得的原则,CPU不必取唤醒所有线程,会减少唤起线程的数量,可以减少CPU唤醒线程的开销,整体的吞吐效率会高点。如果使用的是非公平锁,那就直接尝试竞争锁,竞争得到,就获得锁,获取锁的顺序是随机的。非公平锁:每个线程获取锁的顺序是随机的,并不会遵循。转载 2023-10-05 17:07:29 · 257 阅读 · 0 评论 -
三年开发经验,没用过阻塞队列?
阻塞队列是一种可以在多线程环境下使用,并且支持阻塞等待的队列。线程 1 往阻塞队列中添加元素,当阻塞队列是满的,线程 1就会阻塞,直到队列不满。线程 2 从阻塞队列中移除元素,当阻塞队列是空的,线程 2 会阻塞,直到队列不空;转载 2023-09-09 17:22:15 · 61 阅读 · 1 评论 -
SimpleDateFormat 线程安全问题的六种解决方案
综上所示:在解决解决 SimpleDateFormat 类的线程安全问题的几种方案中,局部变量法由于线程每次执行格式化时间时,都会创建 SimpleDateFormat 类的对象,这会导致创建大量的 SimpleDateFormat 对象,浪费运行空间和消耗服务器的性能,因为 JVM 创建和销毁对象是要耗费性能的。所以,不推荐在高并发要求的生产环境使用。synchronized 锁方式和 Lock 锁方式在处理问题的本质上是一致的,通过加锁的方式,使同一时刻只能有一个线程执行格式化日期和时间的操作。转载 2023-09-03 16:10:35 · 280 阅读 · 0 评论 -
异步线程traceId如何传递
上面两种方式其实本质都是通过Mdc来进行异步线程间的traceId同步,可以看下Mdc的源码,最终还是通过InheritableThreadLocal来实现子线程获取父线程信息//省略若干......原创 2023-02-22 21:25:14 · 2966 阅读 · 0 评论 -
五年经验,还不知道如何优雅终止线程
停止一个线程意味着在任务处理完任务之前停掉正在做的操作,也就是放弃当前的操作。停止一个线程可以用方法,但最好不要用它。虽然它确实可以停止一个正在运行的线程,但是这个方法是不安全的,而且是已被废弃的方法。转载 2023-02-18 18:36:20 · 135 阅读 · 1 评论 -
如何在项目中优雅使用线程池,你学废了么?
fixedThreadPool.submit(() -> System.out.println("异步任务"));这种线程池的使用方式,每次方法调用的时候,需要初始化线程池,使用完线程之后的shutdown。Executors工具类中提供了几种初始化线程池的方式。阿里编码规范中建议,不要用Executors来创建线程池,可能有OOM风险,具体原因可以参见阿里军规--禁用Executors创建线程池。这里可以使用ThreadPoolExecutor来创建线程池。原创 2023-01-11 21:42:49 · 1691 阅读 · 0 评论 -
线程池中线程抛了异常如何处理?
在实际开发中,我们常常会用到线程池,但任务一旦提交到线程池之后,如果发生异常之后,怎么处理?怎么获取到异常信息?在了解这个问题之前,可以先看一下 线程池的源码解析,从链接中我们知道了线程池的提交方式:submit和execute的区别,接下来分别使用他们执行带有异常的任务!看结果是怎么样的!运行结果:可以看到:submit不打印异常信息,而execute则会打印异常信息!转载 2023-01-10 22:46:51 · 266 阅读 · 0 评论 -
面试官:ThreadPoolExecutor 都有哪些核心参数?
所以 Tomcat并没有使用 JUC 原生线程池,利用 TaskQueue 的 offer() 方法巧妙的修改了 JUC 线程池的执行流程,改写后 Tomcat 线程池执行流程如下。然后再说下线程池的 Worker 线程模型,继承 AQS 实现了锁机制。线程启动后执行 runWorker() 方法,runWorker() 方法中调用 getTask() 方法从阻塞队列中获取任务,获取到任务后先执行 beforeExecute() 钩子函数,再执行任务,然后再执行 afterExecute() 钩子函数。转载 2023-01-08 20:12:19 · 196 阅读 · 0 评论 -
自旋锁那点事
自旋”可以理解为“自我旋转”,这里的“旋转”指“循环”,比如 while 循环或者 for 循环。“自旋”就是自己在这里不停地循环,直到目标达成。而不像普通的锁那样,如果获取不到锁就进入阻塞。转载 2022-12-13 21:40:31 · 198 阅读 · 0 评论 -
synchronized 锁和 Lock 锁机制
线程安全是并发编程中的重要关注点,造成线程安全问题的主要原因有两点,一是存在共享数据(也称临界资源),二是存在多条线程共同操作共享数据。因此为了解决这个问题,我们可能需要这样一个方案,当存在多个线程操作共享数据时,需要保证同一时刻有且只有一个线程在操作共享数据,其他线程必须等到该线程处理完数据后再进行,这种方式叫互斥锁,即能达到互斥访问目的的锁,也就是说当一个共享数据被当前正在访问的线程加上互斥锁后,在同一个时刻,其他线程只能处于等待的状态,直到当前线程处理完毕释放该锁。转载 2022-08-22 21:05:53 · 403 阅读 · 0 评论 -
ReentrantLock那点事
一、引言在学习ReentrantLock源码之前,先来回顾一下链表、队列数据结构的基本概念~~二、数据结构2.1 链表(Linked List)小学一、二年级的时候,学校组织户外活动,老师们一般都要求同学之间小手牵着小手。这个场景就很类似一个单链表。每个小朋友可以看作一个节点信息,然后通过牵手的方式,形成整个链表结构。1、链表是以节点的形式来存储数据,可以称之为:链式存储2、每个节点都包含所需要存放对应的数据(data 域),以及指向下一个节点的元素(next 域)。3、链表可以转载 2022-04-10 22:04:36 · 316 阅读 · 1 评论 -
CyclicBarrier源码分析
前言前面,我们在CountDownLatch和CyclicBarrier那点事中简单介绍了CountDownLatch和CyclicBarrier中的使用小demo,同时比对了这两个线程协作工具的特点。这里来和大家一起看看CyclicBarrier的源码。瞅源码先看看CyclicBarrier的类图接口CyclicBarrier其实很简单。从类结构中看到有: await() 方法,猜测应该和 CountDownLatch 是类似的,都是获取同步状态,阻塞自己 Reentr原创 2022-04-05 09:16:32 · 895 阅读 · 0 评论 -
CountDownLatch和CyclicBarrier那点事
前言在多线程协作中,我们经常需要用到countDownLatch和CyclicBarrier,这两个的区别,不管在实际开发还是面试中都是经常遇到的,这里来和大家一起复习下这两个协作工具。CountDownLatchCountDownLatch是一个非常实用的多线程控制工具类,称之为“倒计时器”,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数原创 2022-04-04 18:44:19 · 656 阅读 · 0 评论 -
CountDownLatch源码分析
前言之前我们学习了CountDownLatch在多线程处理任务中的实践,了解countDownLatch的使用方法,这里再和大家一起看下CountDownLatch的源码分析下面代码贴出了CountDownLatch的构造方法。//构造器publicCountDownLatch(intcount){if(count<0)thrownewIllegalArgumentException("count<0");this.sync=newSy...原创 2022-04-03 22:29:36 · 254 阅读 · 0 评论 -
精通多线程,没用过CompletableFuture(三)
前言我们在精通多线程,没用过CompletableFuture(二)中介绍了创建CompletableFuture的四种方式,我们知道了如何通过CompletableFuture来处理异步任务,之前我们对比CompletableFuture和Future说到,CompletableFuture可以通过异步回调来通知异步任务执行完成,这里我们就一起看看CompletableFuture是如何做到这点的。ThenApply/ThenApplyAsync对于ThenApply/ThenApplyAsy原创 2022-03-13 17:09:26 · 1072 阅读 · 0 评论 -
精通多线程,没用过CompletableFuture(二)
前言在精通多线程,没用过CompletableFuture(一)中,我们简单介绍了Future和CompletAbleFuture的基本概念和使用小Demo,这里来和大家一起介绍下使用CompletableFuture创建异步任务的四种方式。创建CompletableFuture对象CompletableFuture提供了四个静态方法用来创建CompletableFuture对象:public static CompletableFuture<Void> runAsync(原创 2022-03-13 15:56:22 · 767 阅读 · 0 评论 -
精通多线程,没用过CompletableFuture(一)
前言日常开发中,我们经常会用到多线程去进行异步任务处理,通过继承Thread类或者实现Runnable接口开启的异步任务,我们要获取异步线程执行结果不是很方便,在JDK1.5已经提供了Future和Callable的实现,我们可以获取异步任务的执行结果了。Future小demo下面通过Futrue的小demo来简单演示下Futrue的用法 @Test public void testFuture() throws ExecutionException, Interrupted原创 2022-03-13 14:42:40 · 594 阅读 · 0 评论 -
CAS原理分析及ABA问题详解
什么是CASCAS即Compare And Swap的缩写,翻译成中文就是比较并交换,其作用是让CPU比较内存中某个值是否和预期的值相同,如果相同则将这个值更新为新值,不相同则不做更新,也就是CAS是原子性的操作(读和写两者同时具有原子性),其实现方式是通过借助C/C++调用CPU指令完成的,所以效率很高。CAS的原理很简单,这里使用一段Java代码来描述public boolean compareAndSwap(int value, int expect, int update) {//转载 2021-10-10 18:04:38 · 301 阅读 · 0 评论 -
5年经验,还不知道线程池是否需要关闭
前言大家在日常开发中会经常用多线程,一般为了合理地管理线程,我们一般会通过线程池来创建线程。那么在使用完线程池之后我们需要显式关闭线程池么?举个栗子下面我们来通过一个demo看看显式关闭线程池是否有必要public class TestShutDown { private static void asynExecuteOne() { ExecutorService executor = Executors.newSingleThreadExecutor();原创 2021-09-06 22:28:44 · 7163 阅读 · 3 评论 -
3年经验,还不知道原子变量
前言在日常多线程开发中,我们经常要保证操作的原子性,比如说常见的i++,要保证操作的原子性,小伙伴的第一反应是Sychronized,确实Sychronized可以保证操作的原子性,但是如果只是简单的i++,没必要使用Sychronized这玩意,我们直接使用java提供的原子变量就ok了。举个小栗子下面是没有使用原子变量的小栗子public class NotAtomicDemo implements Runnable { private int serialNumber = 0原创 2021-09-04 20:52:18 · 210 阅读 · 0 评论 -
CountDownLatch在多线程处理任务中的实践
前言之前语音资源部需要下载一批音频,当时开发一个多线程下载工具,其中多线程处理逻辑,就是将一批任务分配给多个线程去处理,其实代码简化下来就是用多线程处理一个list。简化代码public class HandleThread extends Thread { private static final Log LOGGER = LogFactory.getLog(HandleThread.class); private String threadName; privat原创 2021-01-14 22:13:00 · 311 阅读 · 0 评论 -
FutureTask源码介绍
前言日常开发中,我们经常需要用到多线程异步任务执行,异步任务执行之后,我们需要获取到任务执行的结果,是执行成功了,还是失败了,对于这个场景Runnable肯定是不能满足的,有的小伙伴可能会说Callable可以获取到任务执行的结果。是的没毛病,这里来和大家一起学习Runnable和Callable的合体-FutureTask。简单小demopublic class FeatureTest { public static void main(String args[]) {原创 2020-09-24 22:51:56 · 185 阅读 · 0 评论 -
多线程编程之阻塞队列概述
前言 JDK1.5中引入的接口java.util.concurrent.BlockingQueue定义了以中国线程安全的队列-阻塞队列。BlockingQueue常用的实现类包括ArrayBlockingQueue,LinkedBlockingQueue和SynchronousQueues,下面来和大家一起学习下这三种阻塞队列。阻塞队列描述 阻塞队列按照其存储空间的容量是否受限制来划分,可以分为有界队列和无界队列,有界队列的存储容量限制是由应用存储指定的,无界队列的最大存储容量为I...原创 2020-05-17 17:19:48 · 263 阅读 · 0 评论 -
扒一扒ReentrantLock以及AQS实现原理
前言提到JAVA加锁,我们通常会想到synchronized关键字或者是Java Util Concurrent(后面简称JUC)包下面的Lock,今天就来扒一扒Lock是如何实现的,比如我们可以先提出一些问题:当我们通实例化一个ReentrantLock并且调用它的lock或unlock的时候,这其中发生了什么?如果多个线程同时对同一个锁实例进行lock或unlcok操作,这其中又发生了什...转载 2018-08-25 11:58:57 · 129 阅读 · 0 评论 -
线程中断机制
前言之前我们捋清楚了线程中的sleep(),wait(),join()等方法,这里我们再来学习下java中的线程中断机制。中断是一种协作机制。当一个线程中断另一个线程时,被中断的线程不一定要立即停止正在做的事情。相反,中断是礼貌地请求另一个线程在它愿意并且方便的时候停止它正在做的事情。有些方法,例如 Thread.sleep(),很认真地对待这样的请求,但每个方法不是一定要对中断作出响应。对于...原创 2018-08-21 23:04:42 · 1231 阅读 · 0 评论 -
刨根系列之volatile详解 (二)
前言在刨根系列之volatile详解中,我提到过:volatile只能保证可见性和有序性,无法保证原子性。关于这部分内容,有读者阅读之后表示还是不是很理解,所以我再单独写一篇文章深入分析一下。volatile与有序性在上一篇文章中我们提到过:volatile一个强大的功能,那就是他可以禁止指令重排优化。通过禁止指令重排优化,就可以保证代码程序会严格按照代码的先后顺序执行。那么volat...转载 2018-08-27 21:46:06 · 339 阅读 · 0 评论 -
捋捋sleep(),wait(),join(),yield()
前言常见的线程操作方法有很多,我们通过调用这些方法来进行线程的切换和调度。这里来和大家一起捋捋这些常用的方法。sleep()sleep()是属于Thread类的方法,sleep()方法需要指定等待的时间,它可以让当前正在执行的线程在指定的时间内暂停执行,进入阻塞状态,该方法既可以让其他同优先级或者高优先级的线程得到执行的机会,也可以让低优先级的线程得到执行机会。但是sleep()方法不...原创 2018-08-08 23:41:35 · 172 阅读 · 0 评论 -
刨根系列之volatile详解
前言volatile这个关键字,不仅仅在Java语言中有,在很多语言中都有的,而且其用法和语义也都是不尽相同的。尤其在C语言、C++以及Java中,都有volatile关键字。都可以用来声明变量或者对象。本文就围绕java中的volatile展开,主要介绍volatile的用法、volatile的原理,以及volatile是如何提供可见性和有序性保障的等。volatile的用法vola...转载 2018-08-15 21:57:32 · 444 阅读 · 0 评论 -
synchronized底层原理
前言对于程序员来说,synchronized只是个关键字而已,用起来很简单。之所以我们可以在处理多线程问题时可以不用考虑太多,就是因为这个关键字帮我们屏蔽了很多细节。 那么,本文就围绕synchronized展开,主要介绍其用法、原理,以及如何提供原子性、可见性和有序性保障的等。synchronized的用法synchronized是Java提供的一个并发控制的关键字。主要有两种用法...转载 2018-08-10 22:12:45 · 275 阅读 · 0 评论 -
基于乐观锁的CAS
原文链接http://www.hollischuang.com/archives/1537线程安全众所周知,Java是多线程的。但是,Java对多线程的支持其实是一把双刃剑。一旦涉及到多个线程操作共享资源的情况时,处理不好就可能产生线程安全问题。线程安全性可能是非常复杂的,在没有充足的同步的情况下,多个线程中的操作执行顺序是不可预测的。 Java里面进行多线程通信的主要方式就是共享内...转载 2018-05-15 23:02:21 · 359 阅读 · 0 评论 -
简析ThreadLocal
前言对于ThreadLocal这个类,很多小伙伴可能见的不多,或者说见过,但是没有注意过这个无关痛痒的小玩意。在日常的增删改查中好像也没有用到这个类啊,那么这个类到底有什么用呢??下面来和大家一起总结一下。ThreadLocal中的四个方法ThreadLocal是在jdk1.2中引入的一个类,看到这个名字。大家也估计猜到是和线程有所关联,根据字面意思翻译过来是,线程局部??这是好像也不通啊,其实我们原创 2017-09-13 22:33:29 · 313 阅读 · 1 评论 -
JDK 5.0 中更灵活、更具可伸缩性的锁定机制
前言多线程和并发性并不是什么新内容,但是 Java 语言设计中的创新之一就是,它是第一个直接把跨平台线程模型和正规的内存模型集成到语言中的主流语言。核心类库包含一个 Thread 类,可以用它来构建、启动和操纵线程,Java 语言包括了跨线程传达并发性约束的构造 —— synchronized 和 volatile 。在简化与平台无关的并发类的开发的同时,它决没有使并发类的编写工作变得更繁琐,...转载 2018-08-25 17:06:35 · 110 阅读 · 0 评论 -
到底什么是线程安全
前言说到线程,想必肯定是离不开对于进程的介绍,进程是程序的一次执行,而什么是线程,线程可以理解为进程中的执行的一段程序片段。在一个多任务环境中下面的概念可以帮助我们理解两者间的差别:进程间是独立的,这表现在内存空间,上下文环境;线程运行在进程空间内。 一般来讲(不使用特殊技术)进程是无法突破进程边界存取其他进程内的存储空间;而线程由于处于进程空间内,所以同一进程所产生的线程共享同一内存空间。同...转载 2018-09-16 12:24:50 · 7382 阅读 · 0 评论