![](https://img-blog.csdnimg.cn/306d7b742a8141e8ab426c1c28ba5dbb.jpeg?x-oss-process=image/resize,m_fixed,h_224,w_224)
juc
文章平均质量分 88
juc
小鲁蛋儿
莫道桑榆晚,为霞尚满天。
展开
-
ThreadLocal 详解
如果key使用强引用:业务代码中使用完ThreadLocal ,ThreadLocal Ref被回收了,因为ThreadLocalMap的Entry强引用了threadLocal,造成threadLocal无法被回收,在没有手动删除这个Entry以及CurrentThread依然运行的前提下,始终有强引用链 Thread ref->currentThread->threadLocalMap->entry,Entry就不会被回收(Entry中包括了ThreadLocal实例和value),导致。转载 2023-02-10 20:28:53 · 1325 阅读 · 0 评论 -
AQS源码分析之ConditionObject
ConditionObject是AQS中定义的内部类,实现了Condition接口,在其内部通过链表来维护等待队列(条件队列)。Contidion必须在lock的同步控制块中使用,调用Condition的signal方法并不代表线程可以马上执行,signal方法的作用是将线程所在的节点从等待队列中移除,然后加入到同步队列中,线程的执行始终都需要根据同步状态(即线程是否占有锁)。每个条件变量都会有两个方法,唤醒和等待。当条件满足时,我们就会通过唤醒方法将条件容器内的线程放入同步队列中;转载 2023-02-09 19:52:23 · 596 阅读 · 0 评论 -
Java内存模型之JMM
计算机硬件存储体系计算机存储结构,从本地磁盘到主存到CPU缓存,也就是从硬盘到内存,到CPU。一般对应的程序的操作就是从数据库查数据到内存然后到CPU进行计算。因为有这么多级的缓存(cpu和物理主内存的速度不一致的),CPU的运行并不是直接操作内存而是先把内存里边的数据读到缓存,而内存的读和写操作的时候就会造成不一致的问题。转载 2023-02-06 19:08:28 · 132 阅读 · 0 评论 -
Java线程中断机制
在我们的程序中经常会有一些不达到目的不会退出的线程,例如:我们有一个下载程序线程,该线程在没有下载成功之前是不会退出的,若此时用户觉得下载速度慢,不想下载了,这时就需要用到我们的线程中断机制了,告诉线程,你不要继续执行了,准备好退出吧。当然,线程在不同的状态下遇到中断会产生不同的响应,有点会抛出异常,有的则没有变化,有的则会结束线程。本篇将从以下两个方面来介绍Java中对线程中断机制的具体实现:转载 2023-02-06 18:23:38 · 278 阅读 · 0 评论 -
AQS原理分析
release()是独占模式下线程释放共享资源的顶层入口。它会释放指定量的资源,如果彻底释放了(即state=0),它会唤醒等待队列里的其他线程来获取资源。如果获取锁的线程在release时异常了,没有unpark队列中的其他结点,这时队列中的其他结点会怎么办?是不是没法再被唤醒了?答案是YES,这时,队列中等待锁的线程将永远处于park状态,无法再被唤醒!!!但是我们再回头想想,获取锁的线程在什么情形下会release抛出异常呢??线程突然死掉了?转载 2023-02-06 16:35:11 · 708 阅读 · 1 评论 -
Unsafe类
Java 和 C++ 语言的一个重要区别就是 Java 中我们无法直接操作一块内存区域,不能像 C++ 中那样可以自己申请内存和释放内存。Java 中的 Unsafe 类为我们提供了类似 C++ 手动管理内存的能力。Unsafe 类,全限定名是 sun.misc.Unsafe,Unsafe 的字面意思是不安全,但是指的不是线程安全方面,而是指这个类比较底层, 操作的都是内存,线程等,不建议编程人员直接使用。Unsafe 类是 final 的,不允许继承。转载 2023-02-05 18:47:32 · 502 阅读 · 0 评论 -
JUC的基石:CAS + volatile 实现线程通信
AQS,非阻塞数据结构和原子变量类(java.util.concurrent.atomic包中的类),这些 concurrent 包中的基础类都是使用这种模式来实现的,而 concurrent 包中的高层类又是依赖于这些基础类来实现的,理解这种用法对于源码的阅读会有很好的帮助。Java CAS(compare and swap)自旋操作(JUC基石--CAS+volatile实现线程通信) - 忙碌了一整天的L师傅 - 博客园 (cnblogs.com)转载 2023-02-05 17:04:25 · 1359 阅读 · 0 评论 -
LookSupport 的使用与原理
LockSupport 是一个工具类,提供了基本的线程阻塞和唤醒功能,它是创建锁和其他同步组件的基础工具,内部是使用类实现的。LockSupport 和使用它的线程都会关联一个许可,park 方法表示消耗一个许可,调用 park 方法时,如果许可可用则 park 方法返回,如果没有许可则一直阻塞直到许可可用。unpark 方法表示增加一个许可,多次调用并不会积累许可,因为许可数最大值为 1。原创 2023-02-03 19:21:59 · 640 阅读 · 0 评论 -
join方法原理
join() 方法是一个同步方法,当主线程调用 t1.join() 方法时,主线程先获得了 t1 对象的锁,join() 方法中调用了 t1 对象的 wait() 方法,使主线程进入了 t1 对象的等待池,等到 t1 线程执行结束,主线程才能继续执行。在 Java 中,Thread 类线程执行完 run() 方法后,一定会自动执行 notifyAll() 方法,因为线程在死亡的时候会释放有的资源和锁,自动调用自身的 notifyAll() 方法。,JDK 中,Future 的实现也是采用的此模式。转载 2023-02-03 18:49:06 · 156 阅读 · 0 评论 -
线程八锁问题
考察内容:synchronized 锁住的是哪个对象。原创 2023-02-03 13:57:12 · 359 阅读 · 0 评论 -
ReentrantLock 原理
调用 lock 方法,当为非公平锁时,只要有线程过来就尝试获取锁,如果获取成功AQS的state==0 并且CAS写入成功,将自身设置为独占锁的拥有者state!= 0 但当前独占锁就是自身(表示重入),将state累加;如果获取失败就将自己设置到 AQS 队列的尾部,等待唤醒;原创 2022-10-18 17:39:59 · 2233 阅读 · 1 评论 -
Java线程池源码解析及使用
让有限的工作线程(Worker Thread)来轮流异步处理无限多的任务。也可以将其归类为分工模式,它的典型实现就是线程池,也体现了经典设计模式中的享元模式。例如,海底捞的服务员(线程),轮流处理每位客人的点餐(任务),如果为每位客人都配一名专属的服务员,那么成本就太高了。注意,不同任务类型应该使用不同的线程池,这样能够避免饥饿,并能提升效率。转载 2022-10-17 11:50:38 · 507 阅读 · 0 评论 -
不可变类的使用和设计
下面的代码在运行时,由于 SimpleDateFormat 不是线程安全的。原创 2022-10-15 11:32:15 · 371 阅读 · 0 评论 -
CAS 机制
CAS (Compare And Swap,比较与交换) ,底层是 lock cmpxchg 指令(X86 架构),在单核 CPU 和多核 CPU 下都能够保证【比较-交换】的原子性。在多核状态下,某个核执行到带 lock 的指令时,CPU 会让总线锁住,当这个核把此指令执行完毕,再开启总线。这个过程中不会被线程的调度机制所打断,保证了多个线程对内存操作的准确性,是原子的。CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。转载 2022-10-15 10:37:37 · 1161 阅读 · 0 评论 -
volatile 原理
volatile 是 Java 提供的一种轻量级的同步机制。Java 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量,相比于synchronized(synchronized通常称为重量级锁),volatile更轻量级,因为它不会引起线程上下文的切换和调度。但是volatile 变量的同步性较差(有时它更简单并且开销更低),而且其使用也更容易出错。转载 2022-10-14 10:28:28 · 2451 阅读 · 0 评论 -
线程状态转换
4)当前线程调用 LockSupport.parkNanos(long nanos) 或 LockSupport.parkUntil(long millis) 时,当前线程从 RUNNABLE --> TIMED_WAITING,调用 LockSupport.unpark(目标线程),或调用了线程的 interrupt(),或是等待超时,会让目标线程从 TIMED_WAITING--> RUNNABLE。当前线程等待时间超过了 n 毫秒,当前线程从 TIMED_WAITING --> RUNNABLE。原创 2022-10-13 20:07:11 · 824 阅读 · 0 评论 -
ReentrantLock 使用
obj.wait():让进入 object 监视器的线程到 waitSet 等待obj.notify():在 object 上正在 waitSet 等待的线程中挑一个唤醒obj.notifyAll():让 object 上正在 waitSet 等待的线程全部唤醒它们都是线程之间进行协作的手段,都属于 Object 对象的方法。必须获得此对象的锁,才能调用这几个方法。log.debug("执行....");try {// 让线程在obj上一直等待下去}原创 2022-10-12 20:46:49 · 528 阅读 · 0 评论 -
synchronized原理
由于 Java 面向对象的思想,在 JVM 中需要大量存储对象,存储时为了实现一些额外的功能,需要在对象中添加一些标记字段用于增强对象功能,这些标记字段组成了对象头。原创 2022-10-12 13:50:51 · 722 阅读 · 1 评论 -
线程安全分析
多个线程同时操作list,依然存在线程安全问题,如上源码,ThreadSafeSubClass 类重写了 method3 方法,导致 method1 执行时依然是多个线程操作 list。否,conn对象被多个线程共享,例如:一个线程拿到conn对象,此时另一个线程将conn对象关闭,就会出现线程安全问题。String、Integer 等都是不可变类,因为其内部的状态不可以改变,因此它们的方法都是线程安全的。否,Spring中的对象没有加额外说明的话都是单例模式,需要被共享,就会有线程安全问题。原创 2022-10-10 20:44:41 · 380 阅读 · 0 评论 -
Java 线程的使用
1、单核 cpu 下,多线程不能实际提高程序运行效率,只是为了能够在不同的任务之间切换,不同线程轮流使用,不至于一个线程总占用 cpu,别的线程没法干活。2、多核 cpu 可以并行跑多个线程,但能否提高程序运行效率还是要分情况的。3、IO 操作不占用 cpu,只是我们一般拷贝文件使用的是【阻塞 IO】,这时相当于线程虽然不用cpu,但需要一直等待 IO 结束,没能充分利用线程。所以才有后面的【非阻塞 IO】和【异步 IO】优化。原创 2022-10-09 15:36:32 · 570 阅读 · 0 评论