并发
文章平均质量分 74
主要整理 JAVA 并发相关知识博客
盼兮猫
长亭外 古道边 芳草碧连天
展开
-
ThreadLocal 原理
上篇博客我们提到,ThreadLocal 基于 ThreadLocalMap 实现,其中 ThreadLocalMap 是 Thread 类对象全局变量,通过它保存线程私有属性。ThreadLocalMap 类是 ThreadLocal 类的静态内部类,它的 Key 是 ThreadLocal 对象本身,value 是具体副本值。每个 ThreadLocal 对应一类副本,本篇我们来详解 ThreadLocalMap 原理:下面直接看类定义源码,这里我会省略方法,具体方法实现在后面给出:static c原创 2021-07-01 15:25:28 · 96 阅读 · 1 评论 -
ThreadLocal 详解
ThreadLocal 顾名思义“线程本地变量”,对应到 Java 代码就是线程私有变量,可以把它理解为对于同一个变量,在不同的线程包含不同的副本,并且各个副本之间相互独立下面我们通过一个示例简单认识 ThreadLocal:public class ThreadLocalTest { ThreadLocal<Long> lLocal = new ThreadLocal<>(); ThreadLocal<String> sLocal = new Th原创 2021-06-28 15:56:51 · 392 阅读 · 0 评论 -
Java 阻塞队列
阻塞队列和普通队列主要区别在阻塞二字:阻塞添加:队列已满时,添加元素线程会阻塞,直到队列不满时才唤醒线程执行添加操作阻塞删除:队列元素为空时,删除元素线程会阻塞,直到队列不为空再执行删除操作常见的阻塞队列有 LinkedBlockingQueue 和 ArrayBlockingQueue,其中它们都实现 BlockingQueue 接口,该接口定义了阻塞队列需实现的核心方法:public interface BlockingQueue<E> extends Queue<E>原创 2021-06-02 15:30:32 · 125 阅读 · 1 评论 -
Condition 接口
Condition 是 AQS 为同步机制提供的升级,通过它增强了线程间的交互,其中它的源码如下:public interface Condition { // 使当前线程进入等待状态直到被通知(signal)或中断 void await() throws InterruptedException; // 使当前线程进入等待状态,直到被唤醒,该方法不响应中断要求 void awaitUninterruptibly(); // 使当前线程进入等待状态直到被通知(signal)或中断或超时 lon原创 2021-05-31 17:08:53 · 105 阅读 · 0 评论 -
ReentrantLock 可重入锁
Synchronized 被称为隐式锁,也叫 JVM 锁,因为它锁的持有和释放都是隐式的,无须开发者干预。Java 1.5 引入新的锁机制,其中锁的实现基于 Lock 接口:public interface Lock { // 加锁 void lock(); // 解锁 void unlock(); // 可中断获取锁,获取锁时可响应中断操作 void lockInterruptibly() throws InterruptedException; // 尝试非阻塞获取锁,能够获得返回tru原创 2021-05-31 10:44:46 · 226 阅读 · 0 评论 -
Unsafe 类简单介绍
UnSafe 类源码如下:// JDK 1.7 版本public final class Unsafe { private static final Unsafe theUnsafe; private static native void registerNatives(); private Unsafe() { } @CallerSensitive public static Unsafe getUnsafe() { Class var原创 2021-07-27 15:49:23 · 277 阅读 · 0 评论 -
CAS
CAS 全称 compare and swap,即比较和交换。其中我们主要关注三个属性:V :要更新的变量E:预期值N:新值具体逻辑如下:如果 V 和 E 相等,我们就把 V 更新为 N,否则我们认为当前值已经被修改,不做任何处理。CAS 是典型的乐观锁,相比 Synchronzied 就是悲观锁。所谓乐观是指系统乐观的认为此处不会发生线程安全问题,无须加锁。CAS 基于 UnSafe 类实现,该类中很多方法直接操作内存,属于原子操作,确保 CAS 线程安全。但同样 UnSafe 类如其名,原创 2021-04-20 20:56:14 · 102 阅读 · 0 评论 -
synchronized 锁
线程安全是并发编程的重点,如果一组线程并发执行时不能保证线程安全性问题,就可能造成遭难性的结果,并且不可恢复,因为 Java 线程的调度是完全无序的,我们无法模拟出一模一样的异常场景。保证线程安全性的重点在于保证共享数据同一时刻只能被一个线程占有,互斥锁的概念也是从这来的,synchronzied 就是最常见的互斥锁。线程想要运行 Synchronized 标识的代码必须先拿到锁对象,否则会阻塞等待抢锁。其中 Synchronized 主要有三种使用方法:修饰实例方法:锁是当前对象修饰类方法:锁是原创 2021-04-14 21:06:32 · 77 阅读 · 0 评论 -
关于线上常用的几种线程池配置
线程池可以帮助我们省去创建、回收线程所带来的资源消耗,这也是目前使用线程池的主要原因:下面我根据线上业务依次分析常见的几种线程池并给出个人理解:SingleThreadPool:无界队列,核心线程、最大线程都为 1特点:只有一个线程,阻塞队列使用 LinkedBlockingQueue,链表无界。优点在于保证顺序我个人不推荐使用这种线程池,首先它的应用场景很少,单个线程也无法发挥多核的优势。只适合用于一些边缘业务,不重要也不考虑稳定性的场景可以通过这个线程池慢慢跑如果只是为了保证顺序,我更倾向原创 2021-09-08 22:59:01 · 400 阅读 · 0 评论 -
Java 线程池
频繁的创建和回收线程会对系统带来不小的资源消耗,使用线程池提前创建好一部分线程,当需要使用时直接从线程池拿出来,使用完毕后放回线程池,这样就可以省去频繁创建和回收线程带来的额外消耗。线程池的参数无论使用哪种类型的线程池,最终都会执行如下构造方法:public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keep原创 2021-04-22 11:28:59 · 83 阅读 · 0 评论 -
Java 线程常用方法
Java 线程常用方法有以下几种:Object 方法:wait()notify()notifyAll()静态方法:yield()sleep()currentThread()非静态方法:start()run()join()getState()interrupt()isInterrupted()原创 2021-06-01 15:52:32 · 409 阅读 · 0 评论 -
Java 线程模型
CPU 在任何时刻只能执行一条机器指令,每个进程(线程)获得 CPU 的使用权后才能执行指令。也就是说,多线程的并发运行,实际上就是多条线程轮流获取CPU的使用权,分别执行各自的任务。这种交替执行的好处在于提高效率:任务的完成不可能仅靠 CPU 完成,大多数时候至少需要从内存读取数据,而从内存读取数据相比在 CPU 上运算速度是非常慢的。如果等待一个任务执行完毕后再接着往下执行,那 CPU 绝大多数时候都会处于等待内存读取数据的阶段。线程的实现目前主流的操作系统都支持线程,Java 语言提供在不同平原创 2021-04-14 15:33:54 · 111 阅读 · 0 评论 -
volatile 关键字
volatile是Java虚拟机提供的轻量级的同步机制。其中它的功能主要有以下两种:保证被 volatile 修饰的共享变量对所有线程总数可见的,也就是当一个线程修改了一个被 volatile 修饰共享变量的值,新值总是可以被其他线程立即得知禁止指令重排序优化从上面也就可以看出,volatile 主要保证对象元素的可见性和有序性。volatile 基于内存屏障实现、其中它是一个 CPU 指令,主要作用有两个:保证特定操作的执行顺序(禁止重排序)保证某些变量的内存可见性(保证可原创 2021-04-12 10:14:37 · 77 阅读 · 0 评论 -
JAVA 内存模型
概述Java 内存模型本身是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,定义程序中各个变量的访问方式。Java 内存模型规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作必须在工作内存中进行,首先要将变量从主内存拷贝的自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存,不能直接操作主内存中的变量,工作内存中存储着主内存中的变量副本拷贝。主内存:主要存储的是Java实例对象,所有线程创建的实例对象都存放在主内存中,不管该实例对象是成原创 2021-04-09 11:19:05 · 82 阅读 · 0 评论 -
从操作系统层面理解同步、异步、阻塞、非阻塞
同步和异步描述调用者会不会主动等待函数的返回值,举个例子:public void method() { int result = otherMethod();}像上面这种形式就叫同步,result 会一直等待 otherMethod() 方法执行完毕并拿到返回值public void method() { new Thread(() -> { int result = otherMethod(); });}像上面这种形式就叫异步,主线程不会等待 otherMethod() 方原创 2021-08-18 11:00:05 · 541 阅读 · 1 评论 -
阻塞、非阻塞、并行、并发
同步与异步:同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)同步:发出一个调用时,在没有得到结果之前,该调用就不返回,但是一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用的结果异步:调用在发出后直接返回,没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用举个通俗的例子:你原创 2021-04-09 10:06:52 · 139 阅读 · 0 评论 -
并行和并发
你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。并发的关键是你有处理多个任务的能力,不一定要同时。并行的关键是你有同时处理多个任务的能力。所以我认为它们最关键的点就是:是否是『同时』。(摘自知乎)无论是并行或是并发,核心目的都是为了提高效率。对于计算机来说,相同的任务量,处理所需的时间越少,其效率也就越高。理.原创 2021-04-08 15:39:31 · 147 阅读 · 0 评论