
Java并发编程
文章平均质量分 80
记录Java并发编程相关的知识点。
小小本科生debug
但日子还长,机会也还会有的,不用总是匆匆忙忙那么慌张。
展开
-
HashMap原理分析
HashMap在JDK7中采用的基本存储结构都是数组+链表形式。它的底层维护一个Entry数组。它会根据计算的hashCode将对应的KV键值对存储到该数组中,一旦发生hashCode冲突,那么就会将该KV键值对放到对应的已有元素的后面, 此时便形成了一个链表式的存储结构。原创 2023-01-31 11:25:42 · 422 阅读 · 0 评论 -
队列同步器AQS的实现与分析——共享锁模式
在doAcquireShared(int arg)方法自旋过程中,如果当前节点的前驱节点为头节点时,尝试获取同步状态,如果返回值大于等于0,表示该次获取同步状态成功,调用setHeadAndPropagate()方法设置当前节点为头节点,并从自旋过程中退出。tryAcquireShared()方法是用来获取共享模式下的锁,对于tryAcquireShared()这个方法我们重点看一下他的返回值。当失败的时候返回的是负值,如果返回的是0表示获取共享模式成功但是它下一个节点的共享模式无法获取成功。原创 2023-01-27 21:35:07 · 548 阅读 · 0 评论 -
队列同步器AQS的实现与分析——独占锁模式
然后返回false,代表当前节点不需要挂起,因为pred指向了新的Node,需要重试外层的逻辑。在enq(final Node node)方法中,同步器通过 “死循环” 来保证节点的正确添加,在 “死循环” 中只有通过CAS将节点设置成尾节点之后,当前线程才能从该方法返回,否则,当前线程不断地尝试设置。节点进入同步队列之后,就进入了一个自旋的过程,每个节点(或者说每个线程)都在自省地观察,当条件满足,获取到了同步状态,就可以从这个自旋过程中退出,否则依旧留在这个自旋过程中(并会阻塞节点的线程)原创 2023-01-27 20:28:03 · 570 阅读 · 0 评论 -
ThreadLocal底层原理
ThreadLocal是一个创建线程局部变量的类,ThreadLocal中的变量只有当前自身线程可以访问,别的线程都访问不了。每一个线程都有一个对应的Thread对象,而Thread类有一个ThreadLocalMap类型变量(threadLocals)和一个内部类ThreadLocal。这个threadLocals的key就是ThreadLocal的引用,而value就是当前线程在key所对应的ThreadLocal中存储的值。原创 2023-01-17 23:12:11 · 1044 阅读 · 0 评论 -
JUC下的原子类及源码实现
JUC下的原子类及源码实现一:原子类原子更新基本类型原子更新引用类型原子更新属性原子更新数组Striped64一:原子类Java从JDK 1.5开始提供了java.util.concurrent.atomic包,这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。在atomic包里一共提供了17个类,属于4种类型的原子更新方式,分别是原子更新基本类型、原子更新引用类型、原子更新属性、原子更新数组。atomic包里的类基本都是使用Unsafe实现的包装类,而Unsafe类提供原创 2022-01-27 10:25:15 · 697 阅读 · 0 评论 -
可重入锁ReentrantLock源码解读
ReentrantLock基于AQS,在并发编程中它可以实现公平锁和非公平锁来对共享资源进行同步。同时,和synchronized—样,ReentrantLock支持可重入。除此之外,ReentrantLock在调度上更灵活,支持更多丰富的功能。在Java SE 5 之后,并发包中新增了Lock接口用来实现锁功能,它提供了与synchronized关键字类似的同步功能,只是在使用时需要显示地获取和释放锁。Lock的意义在于提供了区别于synchronized的另一种具有更多广泛操作的同步方式。原创 2022-01-24 23:57:10 · 1021 阅读 · 0 评论 -
队列同步器AQS的实现与分析——概述
队列同步器AQS源码解读)一:队列同步器AQS(AbstractQueuedSynchronizer)1、AQS成员变量:2、FIFO等待队列:3、Node成员变量:4、tryAcquire()方法5、Acquire()方法6、addWaiter()方法7、acquireQueued()方法8、tryRelease()、release()方法一:队列同步器AQS(AbstractQueuedSynchronizer)首先膜拜一下大神Doug Lea队列同步器 AbstractQueuedSynchr原创 2022-01-23 23:34:40 · 721 阅读 · 0 评论 -
synchronized实现原理——悲观锁机制
线程通过CAS去尝试获取锁,一旦获得,那么将会复制该对象的Mark Word到虚拟机栈的Lock Record中,并且将Lock Record中的Owner指针指向该对象锁。这时,这个对象被锁定了,获取了这个对象锁的线程就可以去执行一些任务。其实很简单,在Mark Word中,当锁标志位是01,那么判断倒数第三个bit是否为1,如果是1,代表当前对象的锁状态为偏向锁,于是再去读Mark Word的前23个bit,这23个bit就是线程ID,通过线程ID来确认想要获得对象锁的线程是不是"被偏爱的线程"。原创 2022-01-19 17:31:37 · 1257 阅读 · 0 评论 -
CAS原理——乐观锁机制
当预期值与当前线程的变量值相同时,说明还没线程修改该值,当前线程可以进行修改,也就是执行 CAS 操作。这个共享变量是obj对象的一个成员属性,valueOffset表示这个共享变量在obj类中的内存偏移量。很显然方法都是用native来修饰的,这就表明这个方法不是由Java来实现的。如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。,在变量前面追加上版本号,每次变量更新的时候把版本号加1,那么A->B->A就会变成1A->2B->3A。原创 2022-01-12 11:14:05 · 1028 阅读 · 0 评论 -
Vector的线程安全问题
首先提一个问题,Vector是线程安全的吗?很多人都会回答:vector是线程安全的。确实,通过查看JDK源码中,Vector确实是线程安全的,至少Vector的作者是这么说的。通过观察源码,发现 Vector 类中的大部分方法都是由 synchronized 关键字来修饰的,这也就保证了所有的对外接口都会以 Vector 对象为锁。访问 Vector 的任何方法都必须获得对象的 intrinsic lock (或叫 monitor lock ),所以在Vector内部,所有的方法都不会被多线原创 2021-11-04 16:39:10 · 7843 阅读 · 0 评论 -
线程安全的三大特性(原子性、可见性、有序性)、volatile关键字
volatile关键字介绍一:线程安全的三大特性1、原子性2、可见性3、有序性二:volatile关键字一:线程安全的三大特性1、原子性原子性是指操作是不可分的。其表现在于对于共享变量的某些操作,应该是不可分的,必须连续完成。比如 a++ 操作,实际上 JMM 会分 3 步来完成。①②③读取变量 xttblog 的值xttblog 的值+1将值赋予变量 xttblog这三个操作中任何一个操作过程中,xttblog 的值被人篡改,那么都会出现我们不希望出现的结果。所以我们必须保证这是原子性的原创 2021-10-31 11:40:38 · 8678 阅读 · 2 评论 -
并发安全的集合(CopyOnWriteArrayList、ConcurrentHashMap)
并发安全的集合1、CopyOnWriteArrayList(重要)2、ConcurrentHashMap(重要)紫色的是接口,蓝色的是具体的实现类。1、CopyOnWriteArrayList(重要)CopyOnWrite 写时复制。对于 CopyOnWriteArrayList 集合,正如它的名字所暗示的,它采用复制底层数组的方式来实现写操作。(1)当线程对 CopyOnWriteArrayList 集合执行读取操作时,线程将会直接读取集合本身,无须加锁与阻塞。(2)当线程对 CopyOnW原创 2021-10-25 21:53:05 · 1171 阅读 · 0 评论 -
JUC基础知识(二)
①首先会先判断当前线程数是否超过了core Pool中规定的最大线程数,如果未超出,就会直接在core Pool中创建一个新的线程。类型的对象,通过这个对象可以判断任务是否执行成功,并且可以通过future的get 方法来获取返回值。用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字)。异步:执行一个操作后,可以去执行其他的操作,然后等待通知再回来执行刚才没执行完的操作。4、老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。会响的水壶,简称响水壶)。原创 2021-10-19 11:58:36 · 534 阅读 · 0 评论 -
Java多线程——生产者 / 消费者模型
生产者 / 消费者模型用 wait() 和 notify() 来实现。代码实现:public class ProCumModel { public static void main(String[] args) { Buffer buffer = new Buffer(); Producer producer = new Producer(buffer); Consumer consumer = new Consumer(buffer);原创 2021-09-07 10:09:45 · 195 阅读 · 0 评论 -
多线程实现打印ABC问题——线程间定制化通信
多线程实现打印ABC问题需求:要求三个线程轮换打印ABC十次,每个每个线程打印一个字母public class ABC_Object { private Object lock = new Object(); int num = 0; public void printABC(String name,int no){ for (int i = 0;i < 10;i++) synchronized (lock){ wh原创 2021-09-06 22:53:03 · 234 阅读 · 0 评论 -
Java多线程——Wait与Sleep的区别
Wait与Sleep的区别1、sleep 会暂停当前线程,但是不会释放锁。wait 也会暂停当前线程,但是会释放锁。2、sleep 是Thread类中的方法。Thread.sleep(1000);wait 是Object类中的方法。也就是说所有的对象其实都是有 wait 方法的。new Object().wait();而 sleep 方法只是表示当前线程暂停执行,只能用于 Thread 中。那为什么这样设计呢?原因在于,因为锁其实可以是任意的对象(锁就是监视器Monitor)。那么等待和原创 2021-09-06 21:14:27 · 322 阅读 · 0 评论 -
JUC基础知识(一)
null) {如果此线程是使用单独的,Runnable接口 run 对象,然后Runnable接口调用对象的 run 方法;否则,此方法不执行任何操作并返回。Thread 的子类应重写此方法。Person类实现 run 方法来实现自己的业务逻辑,如果在 main 线程中调用 run 方法,相当于并没有开辟一个线程,run 方法只是一个普通的方法,那么就会把 run 方法执行完毕,才向下执行。原创 2021-09-01 21:59:27 · 369 阅读 · 0 评论