JUC并发编程
文章平均质量分 86
JUC并发编程与源码分析
Anton丶
前路不尽,心已明,行将远......
展开
-
JUC并发编程第十四篇,StampedLock(邮戳锁)为什么比ReentrantReadWriteLock(读写锁)更快!
首先获取读锁,如果cache不可用,则释放读锁,获取写锁,在更改数据之前,再检查一次cacheValid的值,然后修改数据,将cacheValid置为true,然后在释放写锁前获取读锁;但是,当读锁被使用时,如果有线程尝试获取写锁,该写线程会被阻塞,需要释放所有读锁,才可获取写锁。当stamp返回零时,表示线程获取锁失败,并且,当释放锁或者转换锁的时候,都要传入最初获取的stamp值。StampedLock采取乐观获取锁后,其他线程尝试获取写锁时不会被阻塞,在获取乐观读锁后,还需要对结果进行校验。原创 2022-12-16 15:42:03 · 377 阅读 · 0 评论 -
JUC并发编程第十三篇,AQS的作用与体系结构
这个机制主要用的是CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列中,这个队列就是AQS的抽象表现,它将请求共享资源的线程封装成队列的结点(Node),通过CAS、自旋以及 LockSupport.park() 的方式,维护state变量的状态,使并发达到同步的效果。AQS使用一个volatile的 int 类型的成员变量来表示同步状态,通过内置的 FIFO 队列来完成资源获取的排队工作,将每条要去抢占资源的线程封装成一个Node节点来实现锁的分配,通过CAS完成对State值的修改。原创 2022-12-15 15:07:28 · 370 阅读 · 0 评论 -
JUC并发编程第十二篇,详解Synchronized与锁升级
我们都知道,用锁能够保证数据的安全性,但是会带来性能下降;无锁能够基于线程并行提升程序性能,但是会带来安全性问题,为了达到两着的平衡,于是就有了多种锁的实现和锁升级。经过上一节的了解,我们知道了synchronized锁根据对象头中的 Mark Word 中的锁标志位的不同而区分,这一节来学习锁有哪几种类型以及是如何升级的。原创 2022-12-14 16:19:16 · 384 阅读 · 0 评论 -
JUC并发编程第十一篇,Java对象的内存布局
对象头分为对象标记(markOop)和类元信息(klassOop),类元信息存储的是指向该对象类元数据(klass)的首地址。虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐,这部分内存按8字节补充对齐。它会根据对象的状态复用自己的存储空间,在运行期间 MarkWord 里存储的数据会随着锁标志位的变化而变化。对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。对象标记中都保存了什么?Hotspot实现(64位)原创 2022-12-13 15:05:49 · 362 阅读 · 0 评论 -
JUC并发编程第十篇,谈谈ThreadLocal原理与内存泄露的那些事儿
1、ThreadLocal 不是解决线程间共享数据问题的,而是用于 变量在线程间隔离且在方法间共享的场景。2、它隐式的在不同线程内创建独立实例副本,避免了实例线程的安全问题。3、每个线程持有一个只属于自己的Map,维护了ThreadLocal对象与具体实例的映射,该Map只能被持有它的线程访问,故不存在线程安全以及锁的问题。4、ThreadLocalMap 的 Entry 对 ThreadLocal 的引用为弱引用,避免了 ThreadLocal 对象无法被回收的问题。原创 2022-12-12 15:33:38 · 286 阅读 · 0 评论 -
JUC并发编程第九篇,原子操作类分类解析,LongAdder为什么这么快原理分析?
LongAdder在无竞争的情况,跟AtomicLong一样,对同一个base进行操作,当出现竞争关系时则是采用化整为零的做法,从空间换时间,用一个数组cells,将一个value拆分进这个数组cells。LongAdder的基本思路就是分散热点,将value值分散到一个Cell数组中,不同线程会命中到数组的不同槽中,各个线程只对自己槽中的那个值进行CAS操作,这样热点就被分散了,冲突的概率就小很多。携带版本号的引用类型原子类,可以解决ABA问题,可以记录修改过几次。原创 2022-12-08 16:40:56 · 439 阅读 · 0 评论 -
JUC并发编程第八篇,谈谈你对CAS的理解?自旋锁,CAS底层原理和存在的问题?
CAS是JDK提供的非阻塞原子性操作,它通过硬件保证比较-更新的原子性,效率更高且更可靠。compareAndSet 底层源码经过查看源码,找到这几个方法,存在于一个叫UnSafe的类中,UnSafe类是什么呢?Unsafe是CAS的核心类,由于Java方法无法直接访问底层系统,需要通过本地(native)方法来访问,Unsafe相当于一个后门,基于该类可以直接操作特定内存的数据。Unsafe类存在于sun.misc包中,其内部方法操作可以像C的指针一样直接操作内存,Java中CAS的操作执行依赖原创 2022-12-06 23:29:17 · 204 阅读 · 0 评论 -
JUC并发编程第七篇,volatile凭什么可以保证可见性和有序性?我们该如何正确使用它?
内存屏障是一种同步屏障指令,是CPU或编译器在对内存随机访问操作中的一个同步点,目的是为了保证此点之前的所有读写操作都执行完,然后才可以开始执行此点之后的操作,避免代码重排序。内存屏障其实就是一种JVM指令,Java内存模型的重排规则会要求Java编译器在生成JVM指令时插入特定的内存屏障指令,通过这些内存屏障指令,volatile实现了Java内存模型中的 可见性和有序性,但volatile无法保证原子性。原创 2022-12-02 13:57:33 · 462 阅读 · 0 评论 -
JUC并发编程第六篇,带你了解Java内存模型JMM
Java内存模型,简称JMM,是一种抽象的概念,用于描述一组规范约定,这个规范定义了程序中各个变量的读写访问方式,以及一个线程对共享变量的写入和对另一个线程的可见。原创 2022-12-01 16:42:40 · 379 阅读 · 0 评论 -
JUC并发编程第五篇,如何优雅的使用线程中断机制和线程等待唤醒机制?
一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。Java提供了一种用于停止线程的机制——中断。中断只是一种协作机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。若要中断一个线程,你需要手动调用该线程的interrupt方法,该方法也仅仅是将线程对象的中断标识设成true,接着你需要自己写代码不断地检测当前线程的标识位,如果为true,表示别的线程要求这条线程中断,此时究竟该做什么需要你自己写代码实现。原创 2022-11-29 20:00:00 · 397 阅读 · 0 评论 -
JUC并发编程第四篇,Java中的各种锁之乐观锁和悲观锁、公平锁和非公平锁、可重入锁以及死锁基础
当采用非公平锁时,1个线程请求锁获取同步状态,然后释放同步状态,因为不需要考虑是否还有前驱节点,所以刚释放锁的线程,在此刻再次获取同步状态的概率就变得非常大,所以就减少了线程的开销。适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升。公平锁保证了排队的公平性, 避免了“锁饥饿”问题。举例,从日常生活中的卖票场景理解公平锁和非公平锁。从上边的场景看公平锁和非公平锁存在的问题。默认非公平锁和公平锁存在的意义?非公平锁和公平锁源码上的差别。如何选择非公平锁和公平锁。原创 2022-11-27 17:31:59 · 403 阅读 · 0 评论 -
JUC并发编程第三篇,CompletableFuture场景练习,电商比价需求性能提升
如果现在有一些网站物品价格初始数据串,我们想要进行比价,可以将这些数据保存到Redis的Zset里边,保证数据没有重复,然后进行比较,第一种笨办法就是一条数据一条数据的过,但是这样性能不高;第二种,在JUC里边,有一个 CompletableFuture,用他做多线程异步并发是不阻塞的,而且可以自定义线程池,线程池根据数据量的大小伸缩,在数据量变大时仍能保证效率,大大提升程序性能。案例说明:电商比价需求。原创 2022-11-23 07:39:02 · 343 阅读 · 0 评论 -
JUC并发编程第二篇,对Future的改进,CompletableFuture核心使用
异步任务结束时,会自动回调某个对象的方法;异步任务出错时,会自动回调某个对象的方法;主线程设置好回调后,不再关心异步任务的执行,异步任务之间可以顺序执行。原创 2022-11-21 15:51:19 · 313 阅读 · 0 评论 -
JUC并发编程第一篇,复习线程基础知识
对于线程的使用,大家再熟悉不过了,最简单的就是new一个线程,调用它的 start() 方法,这个线程就启动了。进程:是操作系统资源分配的最小单元,是操作系统对一个正在运行的程序的一种抽象,每⼀个进程都有它⾃⼰的内存空间和系统资源。守护线程:是一种特殊的线程,在后台默默地完成一些系统性的服务,比如垃圾回收线程。线程:是操作系统能够进行运算调度的最小单元,⼀个进程会有1个或多个线程。线程的daemon属性为true表示是守护线程,false表示是用户线程。用户线程:是系统的工作线程。原创 2022-11-17 06:43:15 · 274 阅读 · 0 评论