
并发编程
文章平均质量分 57
Mrrr_Li
时间一直都在向前,你也应该一直向前。
展开
-
Java程序有时为什么要采用异步执行?
为什么要给Java语言增添异步执行?其实很简单,在一个业务流程中,有时候会有一些耗费时间的分支任务,如果把这些琐碎且不重要的任务用异步来执行,那么就可以减轻当前线程的执行压力。举个例子吧,例如有个电商网站为了吸引新用户注册,给出了赠送一年优酷会员的优惠。如果我们采用同步的执行方式,用户帐户开通之后,当前线程还要调用优酷系统的接口,开通会员帐户,并且充值一年会员。整个流程加起来还是挺耗费时间的,让新注册用户等待一两分钟才能收到注册成功的通知,用户心里肯定会怀疑:这是什么破电...原创 2022-04-01 20:52:39 · 1390 阅读 · 0 评论 -
集合的线程安全问题
1. 怎么确保一个集合不能被修改?可以使用Collections.unmodifiableCollection(Collectionc)方法来创建一个只读集合,这样改变集合的任何操作都会抛出Java.lang.UnsupportedOperationException异常。示例代码如下:List<String> list = new ArrayList<>(); list. add("x"); Collection<Stri...原创 2021-12-02 10:03:13 · 466 阅读 · 0 评论 -
Java集合的快速失败机制 “fail-fast”?
集合线程安全原创 2021-12-02 09:55:45 · 296 阅读 · 0 评论 -
ReentrantLock 原理
ReentrantLock 原理可以看出是基于AQS框架实现的。 内容较多,直接看笔记吧。1. 非公平锁实现原理加锁解锁流程NonfairSync 继承自 AQS没有竞争时第一个竞争出现时原创 2021-11-30 12:04:39 · 225 阅读 · 0 评论 -
关于ThreadPool的一些注意事项
原创 2021-11-30 08:59:29 · 189 阅读 · 0 评论 -
AQS原理
ThreadPoolExecutor1. 线程池状态ThreadPoolExecutor 使用 int 的高 3 位来表示线程池状态,低 29 位表示线程数量。其中第一位为符号位。 ● 数字上比较,TERMINATED > TIDYING > STOP > SHUTDOWN > RUNNING。因为第一位为符号位,所以RUNNING最小。 ● 这些信息存储在一个原子变量 ctl 中,目的是将线程池状态与线程个...原创 2021-11-29 21:19:49 · 789 阅读 · 0 评论 -
保护性拷贝&无状态
这种通过创建副本对象来避免共享的手段称之为【保护性拷贝(defensive copy)】原创 2021-11-29 19:46:56 · 159 阅读 · 0 评论 -
主线程与守护线程
默认情况下,Java 进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。例:log.debug("开始运行..."); Thread t1 = new Thread(() -> { log.debug("开始运行..."); sleep(2); log.debug("运...原创 2021-11-29 07:07:36 · 1012 阅读 · 0 评论 -
异步模式之工作线程
1. 定义让有限的工作线程(Worker Thread)来轮流异步处理无限多的任务。也可以将其归类为分工模式,它的典型实现就是线程池,也体现了经典设计模式中的享元模式。例如,海底捞的服务员(线程),轮流处理每位客人的点餐(任务),如果为每位客人都配一名专属的服务员,那么成本就太高了(对比另一种多线程设计模式:Thread-Per-Message)注意,不同任务类型应该使用不同的线程池,这样能够避免饥饿,并能提升效率例如,如果一个餐馆的工人既要招呼客...原创 2021-11-27 15:49:14 · 334 阅读 · 0 评论 -
JDK1.8下ThreadPoolExecutor的官方实现
ThreadPoolExecutor1. 线程池状态ThreadPoolExecutor 使用 int 的高 3 位来表示线程池状态,低 29 位表示线程数量。其中第一位为符号位。 ● 数字上比较,TERMINATED > TIDYING > STOP > SHUTDOWN > RUNNING。因为第一位为符号位,所以RUNNING最小。 ● 这些信息存储在一个原子变量 ctl 中,目的是将线程池状态与线程个...原创 2021-11-27 14:49:26 · 678 阅读 · 0 评论 -
自定义线程池
import lombok.extern.slf4j.Slf4j;import sun.misc.Unsafe;import java.util.ArrayDeque;import java.util.Deque;import java.util.HashSet;import java.util.Queue;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicInteger;impor.原创 2021-11-27 09:03:30 · 373 阅读 · 0 评论 -
final 原理
1. 设置 final 变量的原理理解了 volatile 原理,再对比 final 的实现就比较简单了public class TestFinal { final int a = 20;}字节码0: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: aload_05: bipush 207: putfield #2 // Field a:I<-- 写屏障10原创 2021-11-25 21:29:34 · 364 阅读 · 0 评论 -
共享模式之享元模式
public static Long valueOf(long l) { final int offset = 128; if (l >= -128 && l <= 127) { // will cache return LongCache.cache[(int)l + offset]; } return new Long(l);}注意:Byte, Short, Long...原创 2021-11-25 21:09:06 · 862 阅读 · 0 评论 -
第六章——共享模型之无锁&无锁实现共享变量的线程安全性&CAS与volatile
有如下需求,保证 account.withdraw 取款方法的线程安全interface Account { // 获取余额 Integer getBalance(); // 取款 void withdraw(Integer amount); /** * 方法内会启动 1000 个线程,每个线程做 -10 元 的操作 * 如果初始余额为 10000 那么正确的结果应当是 0 */ static void demo(Acc原创 2021-11-25 09:38:15 · 277 阅读 · 0 评论 -
共享模型之内存&习题
balking 模式习题1. 希望 doInit() 方法仅被调用一次,下面的实现是否有问题,为什么? 答:有问题。该类的对象,在多线程环境下会存在问题。比如t1和t2线程并发执行,相继进入init方法,且都读取到initialized值为false之后,执行doInit方法。这样就不满足题目要求。public class TestVolatile { volatile boolean initialized = false; void init() { ...原创 2021-11-24 16:46:52 · 280 阅读 · 0 评论 -
线程安全的double-checked locking单例模式
使用volatile 修饰Singleton ,保证INSTANCE变量的可见性和有序性。 不使用volatile会导致多线程环境下,由于synchronized代码块内的指令重排,导致线程获得未初始化完的单例。见下图。public final class Singleton { private Singleton() { } private static volatile Singleton INSTANCE = null; publ...原创 2021-11-24 10:43:25 · 368 阅读 · 0 评论 -
内存屏障&volatile原理&可见性&有序性
● 可见性○ 写屏障(sfence)保证在该屏障之前的,对共享变量的改动,都同步到主存当中○ 而读屏障(lfence)保证在该屏障之后,对共享变量的读取,加载的是主存中最新数据● 有序性○ 写屏障会确保指令重排序时,不会将写屏障之前的代码排在写屏障之后○ 读屏障会确保指令重排序时,不会将读屏障之后的代码排在读屏障之前p...原创 2021-11-24 09:54:55 · 677 阅读 · 0 评论 -
volatile&synchronized关于对共享变量保护的比较
synchronized可以保护共享变量的原子性、可见性、有序性。因为如果共享变量完全被synchronized保护,那么共享变量在使用过程中不会有原子性、可见性、有序性问题的。但是他不会阻止代码块内的指令重排序。volatile只可以保证可见性和有序性。volatile 修饰的变量,可以禁用指令重排。...原创 2021-11-24 09:01:55 · 406 阅读 · 0 评论 -
monitor&wait notify&join原理
Monitor 原理Monitor 被翻译为监视器或管程。每个 Java 对象都可以关联一个 Monitor 对象,如果使用 synchronized 给对象上锁(重量级)之后,该对象头的Mark Word 中就被设置指向 Monitor 对象的指针。Monitor 结构如下。 ● 刚开始 Monitor 中 Owner 为 null。 ● 当 Thread-2 执行 synchronized(obj) 就会...原创 2021-11-22 15:16:28 · 506 阅读 · 0 评论 -
ReentrantLock特征之可重入和可打断
可重入可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住synchronized可重入举例static final Object obj = new Object();public static void method1() { synchronized( obj ) { // 同步块 A method2(); }...原创 2021-11-21 19:58:54 · 934 阅读 · 1 评论 -
从Java层面理解线程状态转换
Java层面线程有6种状态1. NEW表示新建的线程2. 其中RUNNABLE状态又细分为三种状态。● 运行状态表示线程已经获取了CPU分配的时间片,正在CPU上运行。● 阻塞状态表示线程可能处于IO阻塞。● 可运行状态表示,线程可以由CPU调度,上处理机执行。3. BLOCKED表示阻塞4. WAITING表示等待5. TIMED_WAITING表示有时限的等待6. TERMINATED表示终止态假设有线程 Th...原创 2021-11-21 15:46:55 · 152 阅读 · 0 评论 -
异步模式之生产者/消费者
1. 定义要点● 与前面的保护性暂停中的 GuardObject 不同,不需要产生结果和消费结果的线程一一对应● 消费队列可以用来平衡生产和消费的线程资源● 生产者仅负责产生结果数据,不关心数据该如何处理,而消费者专心处理结果数据● 消息队列是有容量限制的,满时不会再加入数据,空时不会再消耗数据● JDK 中各种阻塞队列,采用的就是这种模式2. 实现//消息class Message { ...原创 2021-11-21 11:21:46 · 156 阅读 · 0 评论 -
同步模式之保护性暂停
1.定义即 Guarded Suspension,用在一个线程等待另一个线程的执行结果要点● 有一个结果需要从一个线程传递到另一个线程,让他们关联同一个 GuardedObject● 如果有结果不断从一个线程到另一个线程那么可以使用消息队列(见生产者/消费者)● JDK 中,join 的实现、Future 的实现,采用的就是此模式● 因为要等待另一方的结果,因此归类到同步模式2. 实现(带超时版的)class...原创 2021-11-21 10:12:27 · 523 阅读 · 0 评论 -
卖票问题中存在的线程安全问题
多个线程共享卖票窗口对象的票数属性,票数属性是共享资源。如果不对临界区代码进行原子性处理,就会存在线程安全问题。处理方法对卖票窗口对象进行上锁:没有线程安全问题的代码package cn.itcast.n4.exercise;import lombok.extern.slf4j.Slf4j;import java.util.ArrayList;import java.util.List;import java.util.Random;import ja...原创 2021-11-20 09:39:26 · 560 阅读 · 0 评论 -
变量的线程安全分析
成员变量和静态变量是否线程安全? ● 如果它们没有共享,则线程安全 ● 如果它们被共享了,根据它们的状态是否能够改变,又分两种情况 ○ 如果只有读操作,则线程安全 ○ 如果有读写操作,则这段代码是临界区,需要考虑线程安全局部变量是否线程安全? ● 局部变量是线程安全的 ● 但局部变量引用的对象则未必 ○ 如果该对象没有逃离方法的作用访问,它...原创 2021-11-20 09:27:10 · 226 阅读 · 0 评论 -
学习并发编程过程中的小思考
● 发生线程安全最底层的原因是对共享资源的访问不是原子性的,是由多个指令组成的。发生线程上下文切换时导致对共享资源的操作发生线程安全问题。导致的结果就是共享资源被访问完后,可能与预期结果不符。代码要防止这种现象发生。● 在主线程中调用子线程的thread.join方法,表示,主线程必须等待子线程执行结束后,才可继续执行join方法之后的代码。● synchronized锁住的对象必须是拥有多个线程共享资源的对象。使用这个图帮助理解...原创 2021-11-20 09:22:38 · 234 阅读 · 0 评论 -
关于Thread类的start方法和synchronized关键字
一些思考● 一个线程内有多个子线程同时start,则获取锁的机会相同。● synchronized 实际是用对象锁保证了临界区内代码的原子性,临界区内的代码对外是不可分割的,不会被线程切换所打断。 ● 原子性是指事件被一次性执行完。通过synchronized关键字,即俗称的【对象锁】,它采用互斥的方式让同一时刻至多只有一个线程能持有【对象锁】,其它线程再想获取这个【对象锁】时就会阻塞住。这样就能保证拥有锁的线程可以安全的执行临界区内的代码,不...原创 2021-11-18 21:38:29 · 424 阅读 · 0 评论 -
共享带来的问题
竞态条件 Race Condition多个线程在临界区内执行,由于代码的执行序列不同而导致结果无法预测,称之为发生了竞态条件* 应用之互斥为了避免临界区的竞态条件发生,有多种手段可以达到目的。● 阻塞式的解决方案:synchronized,Lock● 非阻塞式的解决方案:原子变量本次课使用阻塞式的解决方案:synchronized,来解决上述问题,即俗称的【对象锁】,它采用互斥的方式让同一时刻至多只有一个线程能持有【对象锁】,其它线程再想获取这个【对...原创 2021-11-18 15:56:19 · 109 阅读 · 0 评论 -
什么是线程上下文切换(Thread Context Switch)
因为以下一些原因导致 cpu 不再执行当前的线程,转而执行另一个线程的代码● 线程的 cpu 时间片用完● 垃圾回收● 有更高优先级的线程需要运行● 线程自己调用了 sleep、yield、wait、join、park、synchronized、lock 等方法当 Context Switch 发生时,需要由操作系统保存当前线程的状态,并恢复另一个线程的状态,Java 中对应的概念,就是程序计数器(Program Counter ...原创 2021-11-18 15:03:21 · 227 阅读 · 0 评论