![](https://img-blog.csdnimg.cn/direct/b9db78259da3425aa897c8bb93acb122.jpeg?x-oss-process=image/resize,m_fixed,h_224,w_224)
并发编程
文章平均质量分 84
并发编程真的是一门艺术,需要我辈潜心学习
五敷有你
稳中求进,多平安
展开
-
ThreadLocal详解
如果当前线程再迟迟不结束的话(比如线程池的核心线程),这些key为null的Entry的value就会一直存在一条强引用链:Thread变量 -> Thread对象 -> ThreaLocalMap -> Entry -> value -> Object 永远无法回收,造成内存泄漏。在ThreadLocal和key被回收后,entry中就存在key为null,但value还有值的entry对象,但是永远访问不到,同样除非线程结束。在Entry本身就是一个弱引用,ThreadLocal也是一个弱引用。原创 2024-06-14 22:43:26 · 458 阅读 · 0 评论 -
Synchronized的升级过程
Thread-1加锁失败,进入锁膨胀阶段,为Object对象申请Monitor锁,通过object对象头获取到持有锁的线程,将该线程设置为owner,将对象头的markword设置为指向monitor的地址。线程获取轻量级锁,会使用CAS操作,将MarkWord替换成指向自己的锁记录的指针,如果CAS成功,则说明获取轻量级锁成功,可以进入同步块,如果CAS失败,则表示锁竞争失败,需要升级为重量级锁。如果有取值为null的锁记录,表示重入,这时重置锁记录,表示重入计数-1。原创 2024-05-30 17:35:36 · 721 阅读 · 3 评论 -
ConCurrentHashMap源码学习
ConCurrentHashMap在JDK7之前是分段锁,在JDK8及之后是给Node节点加CAS锁。原创 2024-05-24 09:05:39 · 1091 阅读 · 3 评论 -
Semaphore原理
Semaphore有点像停车场,permits就好像停车位数量,当线程获得了permits就像是获得了停车场显示空余车位减一。刚开始,permits(state) 为 3,这时候5个线程来获取资源。假设其中 Thread-1,Thread-2,Thread-4 cas 竞争成功,而 Thread-0 和 Thread-3 竞争失败,进入 AQS 队列park 阻塞。原创 2024-05-21 10:55:43 · 219 阅读 · 2 评论 -
ReentrantLock可重入原理
interrupt的标记为true,会导致park无效可见,只要permit为1或者中断状态为true,那么执行park就不能够阻塞线程。park只可能消耗掉permit,但不会去消耗掉中断状态。原创 2024-05-16 17:04:29 · 276 阅读 · 4 评论 -
Reentrant Lock非公平锁原理
ReentrantLock 有两种锁:公平锁和非公平锁。原创 2024-05-16 16:41:45 · 1096 阅读 · 0 评论 -
【并发编程】CountDownLatch
CountDownLatch 定义了一个计数器,和一个阻塞队列, 当计数器的值递减为0之前,阻塞队列里面的线程处于挂起状态,当计数器递减到0时会唤醒阻塞队列所有线程,这里的计数器是一个标志,可以表示一个任务一个线程,也可以表示一个倒计时器,CountDownLatch可以解决那些一个或者多个线程在执行之前必须依赖于某些必要的前提业务先执行的场景。统计报表页面涉及到的统计指标数据比较多,每个指标需要单独的去查询统计数据库数据,单个指标只要几秒钟,但是页面的指标有10多个,所以整体下来页面渲染需要将近一分钟。原创 2024-04-04 13:22:39 · 1670 阅读 · 56 评论 -
【并发编程】AQS原理
全称是,是阻塞式锁和相关的同步器工具的框架//同步器类@Override@Override@Override //是否持有独占锁=null){有了自定义同步器,很容易复用 AQS ,实现一个功能完备的自定义锁@Override //加锁,不成功进入等待队列等待@Override //加锁,可以被打断@Override //尝试加锁(一次)@Override //尝试加锁(带超时时间)@Override //解锁@Override //创建条件变量。原创 2024-02-16 15:15:27 · 1963 阅读 · 64 评论 -
【并发编程】ThreadPoolExecutor类
ThreadPoolExecutor 使用 int 的高 3 位来表示线程池状态,低 29 位表示线程数量状态名高三位接受新任务处理阻塞队列任务说明RUNNING111YYSHUTDOWN000NY不会接受新任务,但会处理阻塞队列剩余任务STOP001NN会中断正在执行的任务,并抛弃阻塞队列任务TIDYING010任务全执行完毕,任务线程为0即进入终结TERMINATED011终结状态。原创 2024-02-15 14:03:36 · 1649 阅读 · 44 评论 -
【并发编程】享元模式
定义 英文名称:Flyweight pattern. 当需要重用数量有限的同一类对象时享元模式是一种结构型的设计模式。它的主要。原创 2024-02-09 10:08:33 · 1135 阅读 · 1 评论 -
【并发编程】手写线程池&阻塞队列
/1.任务队列//2.锁//3.生产者条件变量//4.消费者条件变量//5.容量//带超时的阻塞获取try {//将timeOUt转换成统一转换为nstry {//返回值=等待时间-经过的时间return t;}finally {//6. 阻塞获取try {try {return t;}finally {//阻塞添加try {try {try {}finally {//任务队列//队列容量。原创 2024-02-06 17:44:44 · 1995 阅读 · 38 评论 -
【并发编程】原子累加器
JDK8之后有专门做累加的类,效率比自己做快数倍以上。原创 2024-02-05 12:14:09 · 1411 阅读 · 6 评论 -
【并发编程】并发与并行
所谓并发,就是通过一种算法将 CPU 资源合理地分配给多个任务,当一个任务执行 I/O 操作时,CPU 可以转而执行其它的任务,等到 I/O 操作完成以后,或者新的任务遇到 I/O 操作时,CPU 再回到原来的任务继续执行。但是在实际场景中,处于运行状态的任务是非常多的,尤其是电脑和手机,开机就几十个任务,而 CPU 往往只有 4 核、8 核或者 16 核,远低于任务的数量,这个时候就会同时存在并发和并行两种情况:所有核心都要并行工作,并且每个核心还要并发工作。下面是双核处理两个任务。原创 2023-12-13 22:10:46 · 542 阅读 · 0 评论 -
【并发编程】JUC原子操作类
例如,一个线程先读取共享内存数据值A,随后因某种原因,线程暂时挂起,同时另一个线程临时将共享内存数据值先改为B,随后又改回为A。随后挂起线程恢复,并通过CAS比较,最终比较结果将会无变化。在CAS比较前会读取原始数据,随后进行原子CAS操作。,追踪原子引用整个的变化过程,如: A -> B -> A ->C ,通过AtomicStampedReference,我们可以知道,引用变量中途被更改了几次。只要有其它线程【动过了】共享变量,那么自己的 cas 就算失败,这时,仅比较值是不够的,需要再加一个版本号。原创 2024-02-02 11:38:10 · 1076 阅读 · 2 评论 -
【并发编程】共享模型之无锁
它可以用来修饰成员变量和静态成员变量,他可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取它的值,线程操作 volatile 变量都是直接操作主存。其中的关键是 compareAndSet,它的简称就是 CAS (也有 Compare And Swap 的说法),它必须是原子操作。volatile 仅仅保证了共享变量的可见性,让其它线程能够看到最新值,但不能解决指令交错问题(不能保证原子性)前面看到AtomicInteger的解决方法,内部并没有锁来保护共享变量的线程安全,那他是怎么实现呢。原创 2024-02-01 11:27:39 · 1369 阅读 · 2 评论 -
【并发编程】线程安全单例
饿汉式:类加载就会导致该单实例对象被创建懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建。原创 2024-01-30 09:09:23 · 980 阅读 · 1 评论 -
【并发编程】volatile原理
⛺️稳重求进,晒太阳。原创 2024-01-29 16:11:41 · 1079 阅读 · 5 评论 -
【并发编程】happens-before
线程 start 前对变量的写,对该线程开始后对该变量的读可见。他是可见性与有序性的一套规则总结,原创 2024-01-28 17:07:56 · 386 阅读 · 3 评论 -
【并发编程】volatile原理
volatile原理实现是内存屏障原创 2024-01-28 16:39:38 · 889 阅读 · 0 评论 -
【并发编程】指令集并行原理
稳重求进,晒太阳。原创 2024-01-26 08:16:07 · 1216 阅读 · 9 评论 -
【并发编程】Java内存模型
这一章进一步深入学习共享变量在多线程间的【可见性】问题,与多条指令执行时的【有序性】问题。原创 2024-01-26 08:11:07 · 923 阅读 · 0 评论 -
【并发编程】顺序控制&交替输出abc
park不需要while()来判断是否虚假唤醒,因为它指定某个线程唤醒。原创 2024-01-25 09:48:23 · 895 阅读 · 8 评论 -
【并发编程】ReentrantLock
synchronized中也有条件变量,就是waitSet休息室,当条件不满足时进入waitSet等待。可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁。不公平:当一个线程持有锁,其他线程进入阻塞队列等待,当持有者释放锁时,所有线程开始争夺。注意如果是不可中断模式,那么即使使用了 interrupt 也不会让等待中断。如果有竞争,就进入阻塞队列可以被其他线程用interrupt()方法打断。如果是不可重入锁,那么第二次获取锁时,自己也会被锁挡住。原创 2024-01-25 09:29:22 · 1149 阅读 · 2 评论 -
【并发编程】活锁
很多教程把饥饿定义为:一个线程由于优先级太低,始终得不到CPU调度执行,也不能够结束,饥饿的情况不易演示,讲读写锁时会设计饥饿问题。定义:活锁出现在两个线程互相改变对象的结束条件,最后谁也无法结束。原创 2024-01-24 11:32:03 · 365 阅读 · 2 评论 -
【并发编程】哲学家就餐问题
看上图,有五位哲学家,每天循环做两件事:思考,吃面。吃面时每人面前都有一个盘子,盘子左边和右边都有一根筷子,他们在吃面之前需要先拿起左边的筷子再拿起右边的筷子,有了一双筷子就可以吃面了。如果每个哲学家同时都拿着左手的筷子,并在等右边的筷子,就会有死锁的风险。执行不多会,就执行不下去了。原创 2024-01-24 11:28:40 · 1345 阅读 · 2 评论 -
【并发编程】多把锁
多个工作用同一把锁,并发度是很低的。原创 2024-01-23 10:12:18 · 418 阅读 · 5 评论 -
【并发编程】Park & Unpark 你看看不亏
每个线程都有自己的一个 Parker 对象,由三部分组成 _counter , _cond 和 _mutex 打个比喻。1. 调用 Unsafe.unpark(Thread_0) 方法,设置 _counter 为 1。1. 调用 Unsafe.unpark(Thread_0) 方法,设置 _counter 为 1。2. 检查 _counter ,本情况为 0,这时,获得 _mutex 互斥锁。3. 检查 _counter ,本情况为 1,这时线程无需阻塞,继续运行。4. 设置 _counter 为 0。原创 2024-01-22 11:23:49 · 1137 阅读 · 12 评论 -
【并发编程】异步模式之生产者消费者
作为参数传递不是很方便,因此设计一个用来解耦的中间类,这样不仅能够解耦【结果等待者】和【结果生产者】,还能够同时支持多个任务的管理。之后3个postman开始送信,送到后notifyAll(),但是只能叫醒自己锁对象里阻塞的people。3个people开始收信,get()中有wait方法阻塞三个人进入waitSet,然后主线程睡了1秒。右侧的 t1,t3,t5 就好比邮递员如果需要在多个类之间使用 GuardedObject 对象,左侧的 t0,t2,t4 就好比等待邮件的居民,原创 2024-01-22 10:47:23 · 324 阅读 · 0 评论 -
线程状态转换
当调用t.start()方法时,由new ->RUNNABLE。原创 2024-01-20 13:12:51 · 956 阅读 · 0 评论 -
【并发编程】synchornized原理
我们知道,当我们使用synchronized关键字的时候,一个对象a只被一个对象访问的时候,对对象加的锁偏向锁,如果之后出现第二个线程访问a的时候(这里只考虑线程交替执行的情况,不存在竞争),不管线程1是已死亡还是运行状态,此时锁都会升级为轻量锁,并且锁升级过程不可逆。当对象数量超过某个阈值时(默认20, jvm启动时加参数-XX:+PrintFlagsFinal可以打印这个阈值 ),Java会对超过的对象作批量重偏向线程2,此时前20个对象是轻量锁,后面的对象都是偏向锁,且偏向线程2。原创 2024-01-18 16:41:11 · 1478 阅读 · 1 评论 -
【并发编程】同步模式之保护性暂停
同步模式之保护性暂停📝同步模式之保护性暂停这个模式用到的基础就是wait-notify即Guarded Suspension,join的实现,Future的实现,采用的就是此模式。原创 2024-01-19 09:29:55 · 824 阅读 · 2 评论 -
【并发编程】wait/notify
obj.wait() 让进入object监视器的线程到waitSet等待。obj.notify() 在object上正在waitSet等待的线程中随机挑选一个唤醒obj.notifyAll() 让object上正在waitSet等待的线程全部唤醒他们都是线程之间进行协作的手段,都属于Object对象的方法,必须获得此对象的锁,才能调用这几个方法@Slf4jlog.debug("执行....");// 让线程在obj上一直等待下去。原创 2024-01-19 09:20:49 · 1620 阅读 · 0 评论 -
【并发】偏向锁
大多数情况下,锁不仅不存在多线程竞争,而且总是由同一个线程多次获取,为了让线程获得锁的代价更低,引入了偏向锁。原创 2024-01-16 14:52:07 · 617 阅读 · 1 评论 -
【并发】阻塞队列与等待队列
在多线程编程中,等待队列和阻塞队列是两个重要而常用的概念。在本文中,我们将深入探讨等待队列和阻塞队列的概念、特点以及它们在多线程环境下的应用。原创 2024-01-15 18:44:39 · 751 阅读 · 4 评论 -
【并发】共享模型之管程
与预期的结果不同。原创 2024-01-14 16:59:17 · 1098 阅读 · 2 评论 -
多线程基础
线程运行原理。原创 2024-01-14 16:51:02 · 824 阅读 · 0 评论 -
【并发编程】线程池的两种提交方式
线程池是一种并发编程的机制,用于管理和重用线程,以提高应用程序的性能和效率。Java中的execute()和submit()。原创 2024-01-02 20:04:03 · 1267 阅读 · 2 评论 -
【并发】AtomicInteger很安全
在并发编程中,当多个线程对同一个整数进行操作时,可能会出现竞态条件(Race Condition),为了避免这种情况,可以使用。对象,并启动了 5 个线程,每个线程对该对象进行 1000 次的增加操作。能够确保在并发环境中正确地进行原子操作,避免了多线程竞争导致的问题。在这个例子中,我们创建了一个初始值为 0 的。以下是一个简单的示例,展示了如何在多线程环境中使用。保证了对整数的增加操作是原子的,不会出现竞态条件。用于实现原子操作的整数。来确保对整数的操作是原子性的。,因为每个线程增加了。原创 2023-12-30 16:16:09 · 1088 阅读 · 6 评论 -
synchronized的实现原理与应用
在多线程并发中synchronized一直存在,很多人把它称为重量级锁,但随着JavaSE1.6对sycnhronized进行了各种优化后,有些情况就不再那么重了。接下来详解一下JavaSE 1.6为了减少获得锁和释放锁带来的性能消耗并引入了偏向锁和轻量级锁,以及锁的存储结构和升级过程利用synchronized实现同步的基础:Java中每一个对象都可以作为锁。。原创 2023-12-29 19:58:22 · 1033 阅读 · 1 评论 -
【并发编程】你真的懂一个字吗
在16位的系统中(比如8086微机) 1字 (word)= 2字节(byte)= 16(bit)在32位的系统中(比如win32) 1字(word)= 4字节(byte)=32(bit)在64位的系统中(比如win64)1字(word)= 8字节(byte)=64(bit)原创 2023-12-28 16:44:55 · 1022 阅读 · 4 评论