进程, 线程, 协程的区别

进程 Process

进程提供了执行一个程序所需要的所有资源, 一个进程的资源包括虚拟的地址空间, 可执行的代码区, 可用的系统接口, 本地存储, 系统保障的安全上下文(security context), 唯一的进程ID, 环境变量, 优先级, 以及至少一个工作线程. 每个进程都是从一个主线程启动, 然后在运行中创建更多的线程.

  • 进程是操作系统资源分配的最小单位
  • 同一时刻在系统中执行的进程数不会超过核心数
  • 进程之间是隔离的
  • 进程之间有层级关系, 由内核直接创建的进程没有父进程, 除此以外进程都是由其它进程创建的
  • 父进程退出并不会终止子进程

线程 Thread

线程是运行于进程中的一个可以调度运行的实例, 在一个进程中的所有线程, 共用这个进程的虚拟地址空间和其它系统资源(前面进程中提到的进程资源), 除此以外, 还有自己唯一的线程ID, 线程的上下文变量(用于系统调度), 这些上下文变量包含线程的寄存器, 内核堆栈, 环境变量等. 线程也有自己的安全上下文.

进程和线程的区别

  • 进程是操作系统资源分配的基本单位,线程是独立运行和独立调度的基本单位
  • 进程使用单独的地址空间, 而线程(同一个进程下)使用共享地址空间
  • 线程创建和调度的开销比进程小
  • 线程因为共享地址空间, 同一进程的线程间通信很方便

协程 Coroutine

协程是一个特殊的函数, 这个函数可以在运行中被"挂起:, 可以重新在挂起处继续运行. 协程是比线程更加轻量级的一种并发模式.

一个线程中的多个协程的运行是串行的, 一个线程内可以运行多个函数, 但这些函数都是串行运行的, 当一个协程运行时, 其他协程就处于挂起状态. 单独使用协程无法利用CPU的多核资源.

协程和线程的区别

线程是由操作系统调度的, 是操作系统层级的并发, 而协程是完全由程序所控制的, 即在用户态执行, 一个线程可以同时运行多个协程, 运行的开销更小. 线程可以利用CPU的多核资源, 协程不可以, 需要与线程或进程配合.

讲讲ThreadLocal 是什么

ThreadLocal 提供线程的局部变量, 每一个访问该变量的线程在 ThreadLocal 内部都有一个独立的初始化的变量, ThreadLocal 实例变量通常采用private static 在类中修饰. 每个线程都会持有自己的ThreadLocal 实例, 当一个线程结束时,它所持有的所有 ThreadLocal 实例会被回收. ThreadLocal 解决了多线程之间数据隔离问题.

ThreadLocal 使用场景

ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也就是变量在线程间隔离,而在同一线程共享的场景。例如管理Connection,我们希望每个线程只使用一个Connection实例,这个时候用ThreadLocal就很合适.

使用方法为

ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
threadLocal.set(1);
threadLocal.get();
threadLocal.remove();

示例代码

public class Demo {
private static final ThreadLocal<Object> threadLocal = new ThreadLocal<>(); public static void main(String[] args) {
threadLocal.set(new Object());
someMethod();
} static void someMethod() {
// 获取在threadLocal中存储的对象
threadLocal.get();
// 处理
dosomthing();
// 清除
threadLocal.remove();
}
}

ThreadLocal 作为变量的线程隔离是如何实现的?

ThreadLocal 实现原理是什么?

在了解了如何使用之后,看下 ThreadLocal 是如何实现的

ThreadLocal.get()

看get方法的源码,可以看到方法中获取当前线程,并通过当前线程得到一个 ThreadLocalMap,然后通过 this(当前ThreadLocal对象)作为key,从Map中获取Entry

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

For example, the class generates unique identifiers local to each thread. A thread's id is assigned the first time it invokes ThreadId.get() and remains unchanged on subsequent calls.

通过 private static final 类型的变量实现. 在Thread实例中有一个 ThreadLocalMap类型的成员变量, 用来存多个ThreadLocal及其对应的值. 这时候可以new一个或多个ThreadLocal, 这个ThreadLocal实例会自动存入Thread的ThreadLocalMap里

private static final ThreadLocal threadSession = new ThreadLocal();

再往里面set值

threadSession.set(s);

做set操作时, 在ThreadLocalMap里以for循环的方式来取Entry, 判断key是否是这个ThreadLocal, 是的话才set.

用完后可以从ThreadLocalMap里面把这个ThreadLocal实例为key的值remove掉

threadSession.remove();

说说 InheritableThreadLocal 的实现原理?

InheritableThreadLocal 如何弥补 ThreadLocal 不支持继承的特性?

This class extends ThreadLocal to provide inheritance of values from parent thread to child thread: when a child thread is created, the child receives initial values for all inheritable thread-local variables for which the parent has values. Normally the child's values will be identical to the parent's; however, the child's value can be made an arbitrary function of the parent's by overriding the childValue method in this class.

Inheritable thread-local variables are used in preference to ordinary thread-local variables when the per-thread-attribute being maintained in the variable (e.g., User ID, Transaction ID) must be automatically transmitted to any child threads that are created.

由于ThreadLocal设计之初就是为了绑定当前线程, 如果希望当前线程的ThreadLocal能够被子线程使用, 实现方式就会相当困难, 需要用户自己在代码中传递. InheritableThreadLocal主要用于子线程创建时, 需要自动继承父线程的ThreadLocal变量, 方便必要信息的进一步传递.

Thread类中包含 threadLocals 和 inheritableThreadLocals 两个变量, 其中 inheritableThreadLocals 即主要存储可自动向子线程中传递的ThreadLocal.ThreadLocalMap

采用默认方式产生子线程时, inheritThreadLocals=true;若此时父线程inheritableThreadLocals不为空, 则将父线程inheritableThreadLocals传递至子线程

ThreadLocalRandom 如何利用 ThreadLocal 的原理来解决 Random 的局限性?

Thread里有一个 threadLocalRandomSeed 变量, 就是专门用来给ThreadLocalRandom作为seed使用的, 里面还有一个threadLocalRandomProbe变量, 用户判断threadLocalRandomSeed是否已经初始化, 如果probe不为0, 则seed已经初始化.

SpringMVC 中如何使用 ThreadLocal 实现 request scope 作用域 Bean?

对应的代码, 可以看到 RequestAttributes 是用 ThreadLocal 类型存储的

public abstract class RequestContextHolder {
private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal("Request attributes");
private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder = new NamedInheritableThreadLocal("Request context"); @Nullable
public static RequestAttributes getRequestAttributes() {
RequestAttributes attributes = (RequestAttributes)requestAttributesHolder.get();
if(attributes == null) {
attributes = (RequestAttributes)inheritableRequestAttributesHolder.get();
} return attributes;
}

Java多线程专题3: Thread和ThreadLocal的更多相关文章

  1. Java多线程专题5: JUC, 锁

    合集目录 Java多线程专题5: JUC, 锁 什么是可重入锁.公平锁.非公平锁.独占锁.共享锁 可重入锁 ReentrantLock A ReentrantLock is owned by the ...

  2. Java多线程专题1: 并发与并行的基础概念

    合集目录 Java多线程专题1: 并发与并行的基础概念 什么是多线程并发和并行? 并发: Concurrency 特指单核可以处理多任务, 这种机制主要实现于操作系统层面, 用于充分利用单CPU的性能 ...

  3. Java多线程专题2: JMM(Java内存模型)

    合集目录 Java多线程专题2: JMM(Java内存模型) Java中Synchronized关键字的内存语义是什么? If two or more threads share an object, ...

  4. Java多线程专题4: 锁的实现基础 AQS

    合集目录 Java多线程专题4: 锁的实现基础 AQS 对 AQS(AbstractQueuedSynchronizer)的理解 Provides a framework for implementi ...

  5. Java多线程专题6: Queue和List

    合集目录 Java多线程专题6: Queue和List CopyOnWriteArrayList 如何通过写时拷贝实现并发安全的 List? CopyOnWrite(COW), 是计算机程序设计领域中 ...

  6. Java多线程4:Thread中的静态方法

    一.Thread类中的静态方法 Thread类中的静态方法是通过Thread.方法名来调用的,那么问题来了,这个Thread指的是哪个Thread,是所在位置对应的那个Thread嘛?通过下面的例子可 ...

  7. java 多线程2:Thread的实例方法

    Thread类中的方法调用方式: 学习Thread类中的方法是学习多线程的第一步.在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别: 1 ...

  8. java 多线程3:Thread类中的静态方法

    Thread类中的静态方法 Thread类中的静态方法表示操作的线程是"正在执行静态方法所在的代码块的线程".为什么Thread类中要有静态方法,这样就能对CPU当前正在运行的线程 ...

  9. Java多线程系列八——volatile和ThreadLocal

    参考资料: http://ifeve.com/java-memory-model-4/ http://www.infoq.com/cn/articles/java-memory-model-1 htt ...

随机推荐

  1. 【LeetCode】726. Number of Atoms 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/number-o ...

  2. 【LeetCode】427. Construct Quad Tree 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  3. (数据科学学习手札133)利用geopandas绘制拓扑着色地图

    本文示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 我们在绘制某些地图时,为了凸显出每个独立的 ...

  4. [炼丹术]YOLOv5目标检测学习总结

    Yolov5目标检测训练模型学习总结 一.YOLOv5介绍 YOLOv5是一系列在 COCO 数据集上预训练的对象检测架构和模型,代表Ultralytics 对未来视觉 AI 方法的开源研究,结合了在 ...

  5. [opencv]建立纯色图

    1.建立纯白图片,指定大小 250*250为图片的宽高,可自己设置. Mat white = cv::Mat(250,250,CV_8UC3,Scalar(255,255,255)); 2.建立纯黑图 ...

  6. Java初学者作业——实现控制台的猜数字游戏。游戏运行时产生一个1~100之间的随机数字

    返回本章节 返回作业目录 需求说明: (1)实现控制台的猜数字游戏.游戏运行时产生一个1-100之间的随机数字 (2)要求用户从控制台输入数字,若输入的数字比随机数小,则输出"太小了,再大一 ...

  7. JavaScript交互式网页设计 • 【第3章 JavaScript浏览器对象模型】

    全部章节   >>>> 本章目录 3.1 浏览器对象模型 3.1.1 浏览器对象模型 3.2 window 对象 3.2.1 window 对象的常用属性及方法 3.2.2 使 ...

  8. MATLAB/SIMULINK生成代码错误之change the default character encoding setting

    SIMULINK点击生成C代码报错 错误提示: Error encountered while executing PostCodeGenCommand for model 'RTW_sc3': Cl ...

  9. 初识python 之 mysql数据库基本操作

    import pymysql 注:所有插入.修改.删除操作都必须要提交(conn.commit()) 连接数据库: conn = pymysql.connect( host = '127.0.0.1' ...

  10. RabbitMQ --- 直连交换机 【 有回调方法,获取消费结果 】

    1.前言 上一随笔详细记录了直连交换机的方法,发送的消息是异步的,如果消息未被消费者消费,那么可以一直存在消息队列中. 那么有没有办法做一个回调,当消息被消费后,被通知消息成功被消费者消费啦? 答案是 ...