JUC
文章平均质量分 71
wendi➣
人生如程序,要么循环,要么选择
展开
-
volatile深入
1.在多个个线程工作内存看起来互无关联的情况下是怎么做到保证变量的可见性的? 最初通过总线,总线就是一条共享的通信链路,它用一套线路来连接多个子系统。最初实现就是通过总线加锁的方式也就是上面的lock与unlock操作,但是这种方式存在很大的弊端。会将我们的并行转换为串行,从而失去了多线程的意义。 因为内存和CPU的速度差太多,为了解决数据不一致问题,在CPU内部设置了少量的高速缓存,目前流行的3级缓存,那么如何在多核情况下又有多个L1级缓存,来保证数据一致性,这时候推出了MESI缓存一致性协议。然后CPU原创 2021-10-09 09:23:16 · 80 阅读 · 0 评论 -
CAS和AtomicLong和LongAdder
1、Java中,锁占了并发的一席之地,但是锁带来的弊端就是线程会频繁的阻塞挂起,导致上下文的切换和重新调度,增加了系统开销。CAS 即 Compare and Swap(Change),是 JDK 提供的非阻塞原子性操作 , 它通过硬件保证了比较更新操作的原子性 ,有效减小了因为上下文切换导致的开销问题。 CAS底层使用的是lock cmpxchg指令,在单核CPU和多核CPU下都能保证【比较-交换】的原子性。在多核状态下,某个核执行到带lock的指令时,CPU会让总线锁住,当这个核把此指令执行完毕,再开启原创 2021-09-16 15:48:27 · 117 阅读 · 0 评论 -
AQS简介
AQS数据结构是基于虚拟的双向链表(CLH)加state资源的状态,底层还是基于CAS算法,通过CAS自旋来进行修改state的值 CLH就是虚拟的双向队列。没有实际的队列,将请求封装成CLH队列中的一个结点,结点和结点存在关系 里面的核心方法,通过tryAcquire尝试获取锁,然后通过addWaiter进行CAS,然后加入CLH中,acquireQueued判断是否可以获取锁,当线程到CLH队列头部的时候,进行一个尝试获取锁,更新锁的状态,如果更新成功,就表示获取到了锁然后移除队列。 AQS定义两种资源原创 2021-06-10 15:59:25 · 147 阅读 · 0 评论 -
线程池三种创建方式和自定义线程池ThreadPoolExecutor
为什么要用线程池? 线程池的优势: 线程池做的工作只要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,超出数量的线程排队等候,等其他线程执行完毕,再从队列中取出任务来执行。 它的主要特点为: 1.线程复用; 2.控制最大并发数; 3.管理线程。 第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的销耗。 第二:提高响应速度。当任务到达时,任务可以不需要等待线程创建就能立即执行。 第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创原创 2020-11-18 18:43:08 · 396 阅读 · 0 评论 -
高并发的单例模式
哪里用过volatile? 单线程下理想情况应该只执行一次 解决办法可以加synchronized,但是加这个太重了,锁死整个方法,这时候可以用DCL(double check lock)双端检索机制 DCL单例模式,任然存在隐患,因为有指令重排的存在,所以可以加上volatile来禁止指令重排 ...原创 2020-11-18 18:23:04 · 120 阅读 · 0 评论 -
CAS 乐观锁和ABA问题
CAS====》compareAndSet 如果主物理内存的值跟线程期望值一样,就修改为我的更新值,不一样,就失败,需要重新获取主物理内存的值 底层基于usafe,而这个类是rt.jar包sun.misc.unsafe原生类,靠的里面cpu原语保证原子性,工作思想还是靠的cas,比较和交换 CAS的缺点: 1.循环时间长开销大 2.只能保证一个共享变量的原子操作 3.会产生ABA问题 “ABA问题” 简称狸猫换太子 CAS算法实现一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并替换,那么在这个时原创 2020-11-14 17:23:33 · 140 阅读 · 0 评论 -
valotitle 轻量级 同步机制
可以理解为乞丐版的synchronized 三大特性: 1.保证可见性 2.不保证原子性 3.禁止指令重排 (1).可见性验证 添加volatile (2).验证原子性 为什么出现次数少的情况? 假设ABC三个线程,ABC线程可能同时读到一样的值是1到各自的内存空间,A线程修改为2,写入了主内存,通知其他线程值已经修改,这时候的BC也修改为2,准备写入回主内存的时候,被挂起,然后通知没有收到,这时候BC线程回来之后,没有接收到最新的值,所以又把2写入回主内存,这时候,主内存的2被覆盖,这就是写覆原创 2020-11-14 17:03:28 · 178 阅读 · 0 评论 -
生产者消费者之阻塞队列版本
通过标志位的可见,和原子的一致,和阻塞队列,实现生产者和消费者同步原创 2020-11-14 17:02:43 · 68 阅读 · 0 评论 -
自旋锁SpinLock小案例
自旋锁(spinlock) 是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU原创 2020-11-13 22:38:27 · 228 阅读 · 0 评论 -
公平锁非公平锁和可重入锁(递归锁)
可重入锁(也叫做递归琐) 指的是同一线程外层函数获得锁之后,内层递归函数仍然能获取该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁 也就是说,线程可以进入任何一个它已经拥有的锁所同步着的代码块。 synchronized版本 Reentrantlock版本 比如房子有一个大门,有一把琐,虽然卫生间也有一把锁,但是进入大门之后,就可以随意进入卫生间 ...原创 2020-11-13 22:36:00 · 332 阅读 · 0 评论 -
读写锁(ReadwriteLock)
读写锁 多个线程同时读一个资源类没有任何问题,所以为了满足并发量,读取共享资源应该可以同时但是,如果有一个线程想去写共享资源,就不应该再有其它线程可以对该资源进行读或写 结果 总结 读-读能共存 读-写不能共存 写-写不能共存 ...原创 2020-11-12 09:01:27 · 162 阅读 · 0 评论 -
JUC强大的三个辅助类
CountDownLatch 主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞。其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞), 当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行 CyclicBarrier 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点,跟CountDownLatch相反,加一 semaphore 主要用于多线程的并发控制,和资源的互斥 在信号量上我们定义两种操作: acquire原创 2020-11-10 17:50:00 · 187 阅读 · 0 评论 -
多线程的第三种模式(callable)
我们创建线程的方式有 Thread(Runnable target, String name) 分配新的 Thread 对象。 而我们的Callable接口与Runnable接口没有关系,怎么办呢? 这是找一个与两个接口都有关系的类 FutureTask 这个类实现了Runnable,并且它有一个构造方法 FutureTask(Callable callable) 创建一个 FutureTask,一旦运行就执行给定的 Callable。 这时候就把两个接口联系起来了 get方法一般放在最后一行 主线程不耽原创 2020-11-08 22:35:50 · 104 阅读 · 0 评论 -
condition的作用
多线程之间按顺序调用,实现A->B->C三个线程启动,要求如下: A打印5次,B打印10次,C打印15次接着A打印5次,BB打印10次,C打印15次…来10轮 1.高聚低合前提下,线程操作资源类 2.交互判断/干活/通知 3.多线程交互中,必须要防止多线程的虚假唤醒,也即(判断只用while,不能用if) 4.标志位 condition的作用 ,精准打击 资源类 三个方法 整合成一个方法 ...原创 2020-11-07 21:35:03 · 526 阅读 · 0 评论 -
基于Lock的卖票和生产者消费者案例
1.三个售票员卖出30张票 线程 操作(对外暴露的调用方法) 资源类 2.生产者消费者问题 题目:现在两个线程,可以操作初始值为零的一个变量,实现一个线程对该变量加1,一个线程对该变量减1,实现交替,来10轮,变量初始值为零。 1.高聚低合前提下,线程操作资源类 2.交互判断/干活/通知 3.多线程交互中,必须要防止多线程的虚假唤醒,也即(判断只用while,不能用if) ...原创 2020-11-07 15:41:33 · 93 阅读 · 0 评论