
juc
文章平均质量分 57
王佑辉
个人笔记,多谢指正,不喜勿喷
展开
-
【juc】AQS的acquire底层逻辑?
1.如果tryAcquire返回false,表示获取锁失败,此时当前线程会被封装成一个Node节点,并加入到AQS的同步队列(一个双向链表)的尾部。1.当同步状态被释放时(即某个线程调用了release方法),AQS会从等待队列中取出一个线程(通常是队列的头节点),并唤醒它。4.如果前驱节点的状态大于0,表示前驱节点已经被取消等待,此时当前线程会尝试跳过已取消的节点,继续检查下一个前驱节点的状态。4.如果资源当前不可用,则当前线程会被加入到等待队列中并进入阻塞状态,直到资源被释放且当前线程被唤醒。原创 2025-01-03 16:09:05 · 361 阅读 · 0 评论 -
【juc】公平和非公平锁的直观体现?
1.获取锁的顺序:非公平锁允许多个线程在获取锁时直接尝试去获取,而不考虑申请锁的顺序。在高并发的情况下,这有可能导致后申请的线程比先申请的线程优先获取锁,从而造成优先级反转或饥饿现象。1.获取锁的顺序:公平锁保证线程按照申请锁的顺序来获取锁,类似于排队打饭,先来后到。1.在Java的并发工具类(JUC)中,ReentrantLock提供了公平锁和非公平锁两种模式,它们的直观体现主要体现在线程获取锁的。然而,这也可能导致线程饥饿问题。2.JUC中的公平锁和非公平锁在获取锁的顺序和性能特性上存在着明显的差异。原创 2025-01-03 14:52:19 · 322 阅读 · 0 评论 -
【juc】Lock锁和AQS的继承关系
1.AQS是Java并发包中的一个抽象类,它实现了同步器的基本框架,包括同步状态的维护、线程的排队、等待与唤醒等底层操作。2.AQS通过内部维护的一个FIFO双向队列(CLH同步队列)来管理同步状态以及等待获取同步状态的线程。原创 2025-01-02 19:27:31 · 294 阅读 · 0 评论 -
【juc】AQS是什么
1.AQS只是一个框架,只定义了一个接口,具体资源的获取、释放都交由自定义同步器去实现。2.不同的自定义同步器争用共享资源的方式也不同。3.自定义同步器在实现时只需实现共享资源state的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队、唤醒出队等),AQS已经在顶层实现好,不需要具体的同步器再做处理。原创 2025-01-02 19:20:19 · 414 阅读 · 0 评论 -
【juc】ReentrantLock的实现原理
1.尝试获取锁:当一个线程尝试获取锁时,它会首先尝试通过CAS(Compare-And-Swap)操作将锁的状态从“未锁定”(0)修改为当前线程的ID(或其他表示锁持有的值)。2.锁的状态通常用一个整数(通常是32位)来表示,其中高位的几位用于表示锁的状态,低位的几位用于记录重入的次数(即同一个线程持有锁的次数)。1.公平锁:按照线程请求锁的顺序来分配锁,即先请求的线程先获得锁。2.唤醒后继节点:如果锁状态变为“未锁定”,则持有锁的线程会唤醒同步队列中的下一个等待线程,使其有机会尝试获取锁。原创 2024-11-13 22:11:03 · 430 阅读 · 0 评论 -
【juc】什么是可重入,什么是可重入锁,它用来解决什么问题
1.可重入(reentrant)指的是某个资源或方法在被一个线程占用(或称为“进入”)之后,同一个线程可以再次进入(或称为“重入”)这个资源或方法而不会引起冲突或错误。1.当一个方法(或代码块)被设计为可以递归调用自身时,如果没有使用可重入锁,那么在递归过程中再次尝试获取同一个锁时就会失败,从而导致死锁或异常。2.当一个线程需要在持有锁的情况下调用另一个需要相同锁的方法时,如果使用不可重入的锁,就需要先释放锁再获取锁,这会增加上下文切换和锁竞争的开销。1.使用可重入锁可以简化多线程编程中的锁管理。原创 2024-11-13 21:38:20 · 368 阅读 · 0 评论 -
【java】volatile关键字及底层实现原理
2.这是基于屏障指令实现的,当一个变量被声明为volatile时,编译器和处理器会注意到这个变量可能会被其他线程并发地访问,从而避免线程之间的数据竞争,并确保多线程环境下变量的值是最新的。2.当一个线程对volatile变量进行写操作时,JVM会向处理器发送一条“lock”指令,将该变量所在缓存行的数据写回主内存,并使其他处理器的缓存失效。3.当其他线程读取该变量时,由于缓存一致性协议的存在,它们会发现该变量所在的内存行已被标记为“脏”,从而立即将自身的缓存失效,并重新从主内存中读取最新值。原创 2024-11-13 14:19:36 · 430 阅读 · 0 评论 -
【juc】谈谈CAS机制
2.实现线程安全的计数器:通过CAS机制,可以实现线程安全的计数器,如AtomicInteger、AtomicLong等,这些计数器在多线程环境下可以确保计数的准确性。4.CAS机制是一种重要的并发编程技术,它具有原子性、非阻塞性和无锁算法等特点,可以用于实现无锁数据结构、线程安全的计数器和并发容器等。1.在CAS操作过程中,如果变量的值被改为了A、B、再改回A,而CAS操作是能够成功的,这可能导致程序出现意外的结果。:CAS机制是实现无锁算法的基础,它避免了传统锁机制中可能发生的死锁和线程饥饿问题。原创 2024-11-13 13:41:53 · 302 阅读 · 0 评论 -
【juc】AbstractQueuedSynchronized为什么采用双向链表
2.而在AQS中,当某个线程释放锁并需要唤醒后继线程时,如果采用单向链表,则需要从头节点开始遍历以找到要删除和唤醒的节点,这会增加时间复杂度。3.双向链表可以保持线程加入等待队列的顺序,即先加入的线程排在队列前面,后加入的线程排在队列后面,这有助于实现公平性。3.双向链表可以使得这种删除操作更加高效,因为可以直接通过前驱节点的引用找到需要删除的节点,而无需从头节点开始遍历。4.每个节点都有指向其前驱和后继节点的引用,因此当前驱节点的状态发生变化时,可以立即影响到后继节点。原创 2024-11-13 11:01:54 · 320 阅读 · 0 评论 -
【juc】ConcurrentHashMap
在JDK 1.8中,引入了多线程并发扩容的机制,多个线程可以同时对原始数组进行分片后,每个线程负责一个分片的数据迁移,从而提升了扩容过程中数据迁移的效率。4.但在JDK 1.8及之后的版本中,虽然概念上仍然保留了分段锁的思想,但实际上是通过更细粒度的锁(如CAS操作和synchronized关键字对链表头节点的加锁)来实现的。:由于ConcurrentHashMap的读操作是线程安全的,且不需要获取锁,因此读操作在没有竞争的情况下几乎没有性能损耗。2.重新分配数组:创建一个新的数组,其长度为新容量的值。原创 2024-11-11 18:03:13 · 597 阅读 · 0 评论 -
【juc】cyclicbarrier人数凑齐发车
【代码】【juc】人数凑齐发车。原创 2023-10-08 21:52:08 · 195 阅读 · 0 评论 -
【juc】future并行执行并获取返回值
【代码】【juc】future并行执行并获取返回值。原创 2023-10-08 20:48:06 · 322 阅读 · 0 评论 -
【juc】countdownlatch实现并发网络请求
【代码】【juc】countdownlatch实现并发网络请求。原创 2023-10-07 22:19:55 · 220 阅读 · 0 评论 -
【juc】countdownlatch实现游戏进度
【代码】【juc】countdownlatch实现游戏进度。原创 2023-10-07 21:28:34 · 294 阅读 · 0 评论 -
【juc】ReentrantReadWriteLock之缓存(仅当学习)
2.先查缓存,没有再去查库。1.针对于读多写少的情况。原创 2023-09-04 14:18:26 · 708 阅读 · 0 评论 -
【juc】读写锁ReentrantReadWriteLock
3.提供一个数据容器类,内部分别使用读锁保护数据的read()方法,写锁保护数据的write()方法。2.类似于数据库中的select …lock in share mode。2.不支持重入时升级:持有读锁的情况下去获取写锁,会导致获取写锁永久等待。1.当读操作远远高于写操作时,使用读写锁让读读可以并发,来提高性能。3.支持重入时降级:持有写锁的情况下去获取读锁。1.读写不支持条件变量。原创 2023-08-29 16:44:59 · 1496 阅读 · 0 评论 -
【juc】AQS原理
1.是一个抽象父类,全称是AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架2.用法是同步器类继承该父类,去实现父类的方法,调用同步器类的方法达到加锁、解锁等目的。原创 2023-07-29 21:44:05 · 281 阅读 · 0 评论 -
【juc】自定义连接池
2.连接保活(可用性检测)1.连接的动态增长和收缩。原创 2023-07-09 15:46:04 · 359 阅读 · 2 评论 -
【juc】不可变类DateTimeFormatter
【代码】【juc】不可变类DateTimeFormatter。原创 2023-07-08 21:23:39 · 223 阅读 · 0 评论 -
【juc】Unsafe类
3.Unsafe类不是表面上的线程是否安全的类,因为该类是底层,操作的是内存和线程,不建议编程人员直接使用。1.被final关键字修饰,不能被继承。2.是sun.misc包下。原创 2023-07-07 14:48:19 · 305 阅读 · 0 评论 -
【juc】字段更新器
2.只能配合volatile修饰的字段使用,否则会出异常Exception in thread “main” java.lang.IllegalArgumentException: Must be volatile type。3.常见有AtomicReferenceFieldUpdate、AtomicIntegerFieldUpdate、AtomicLongFieldUpdate。1.利用字段更新器可以针对对象的域(Field)原创 2023-06-29 21:55:36 · 191 阅读 · 0 评论 -
【juc】原子数组
【代码】【juc】原子数组。原创 2023-06-29 11:15:56 · 270 阅读 · 0 评论 -
【多线程】原子引用AtomicMarkableReference
1.标记资源是否被修改。原创 2023-06-14 22:39:17 · 195 阅读 · 0 评论 -
【多线程】原子引用ABA问题
4.如果希望主线程能感知到其它线程动过该共享变量,则cas失败,所以比较值是不能解决问题的,需要再加一个版本号。3.对于主线程仅能判断出共享变量的值与最初值A是否相同,不能感知到A改为B又改回A的情况。2.在这期间,线程1将共享变量由A改为B,线程2再将共享变量B改为A。1.主线程准备将共享变量由A改为C。原创 2023-06-13 21:33:38 · 280 阅读 · 0 评论 -
【juc】原子整数AtomicInteger
【代码】【juc】原子整数AtomicInteger。原创 2023-06-12 21:01:06 · 93 阅读 · 0 评论 -
【多线程】为什么不建议使用Executors来创建线程池?
单个线程线程池创建时FinalizableDelegatedExecutorService用的是装饰器模式,只对外暴露ExecutorService接口,不能调用ThreadPoolExecutor中特有的方法,固定数量线程池对外暴露的是ThreadPoolExecutor对象,可以强转,调用setCorePoolSize等方法进行修改。4.与自己创建的线程的区别:a.自己创建一个单线程串行执行任务,任务执行失败而终止则没有任务不就措施,线程池执行失败会新建一个线程,保证线程池的正常工作;原创 2023-04-22 20:34:00 · 1026 阅读 · 0 评论 -
【juc】ReentrantLock可重入锁
2.ReentrantLock的条件变量支持多个,synchronized不满足条件的线程都在同一个waitSet中等待,ReentrantLock可以让不同条件不满足的线程在不同的地方等待。3.可以设置为公平锁:竞争不到锁的线程在等待过程中,当锁释放后,谁先等待的谁先得到锁(先进先出);3.其它线程获取到锁,然后释放锁,只要时间小于tryLock的时间,尝试获取锁还是可以成功的。2.可以设置超时时间:规定时间内,线程1争抢不了锁,可以放弃锁的竞争。1.可中断:线程2可以让线程1获取的锁取消掉。原创 2023-04-09 21:52:27 · 535 阅读 · 0 评论 -
【多线程】哲学家就餐死锁问题
【代码】【多线程】哲学家就餐死锁问题。原创 2023-04-09 13:51:41 · 214 阅读 · 0 评论 -
【juc】LockSupport的park和unpark方法
4.例子1: 在线程1中执行LockSupport.park()后,_counter一开始为0,然后线程1进入_cond等待队列中阻塞,线程2中执行LockSupport.park(线程1)后,线程1在等待队列中阻塞,唤醒线程1,将_counter改为1,线程1恢复运行,再将_counter改为0。3.调用unpark()方法:线程2调用unpark(线程1)方法,如果发现线程1在等待队列_cond中阻塞,便唤醒线程1,并将_counter标识改为1,线程1恢复运行再将_counter标识改为0;原创 2023-04-08 19:53:54 · 321 阅读 · 0 评论 -
【juc】wait和notify原理
6.waitset中的线程1和线程3会在owner指向的线程1调用notify或者notifyAll时唤醒,被唤醒后,不会立刻获得锁,还是要进入entrylist等待下一次竞争。2.线程1在执行的过程中发现条件a不满足执行不下去了,此时线程1可以调用wait方法,那么线程1就进入waitset进行等待,状态为waiting。5.waitset中的线程是获取到了锁,但又主动放弃了锁;3.线程4准备给对象A加锁,发现当前对象A的monitor的owner是线程2,线程4则会进入entryList中准备竞争。原创 2023-04-06 23:09:00 · 294 阅读 · 0 评论 -
【juc】monitor锁
3.锁记录中包含 对象指针(引用地址)和 锁记录地址和轻量级锁标识00,加锁后,对象指针会指向对象A,并且拿锁记录的地址和轻量级锁标识00去交换对象A的对象头的mark word,如果交换成功了,对象A的对象头中的mark word存的是锁记录的地址和轻量级锁标识00,锁记录中存的则是对象A的对象头markword之前存的信息(hashcode、分代gc年龄、是否偏向),该线程则对对象A加上了锁。4.当线程1给对象A上了synchronized锁,对象A关联的monitor的owner则为线程1。原创 2023-04-05 21:26:19 · 612 阅读 · 0 评论 -
【多线程】创建线程有哪几种方式
1.创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,且该call()方法有返回值。2.创建Runnable实现类的实例,并将其作为Thread的target来创建Thread对象,Thread对象为线程对象。1.定义Runnable接口的实现类,并实现该接口的run()方法,该run()方法将作为线程执行体。1.定义Thread类的子类,并重写该类的run()方法,该run()方法将作为线程执行体。3.调用线程对象的start()方法来启动该线程。原创 2023-03-26 21:49:47 · 299 阅读 · 0 评论