【OSTEP】并发:线程与多线程

2024-04-05 05:44
文章标签 线程 并发 多线程 ostep

本文主要是介绍【OSTEP】并发:线程与多线程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

" A flow of control within a process that consists of a PC, a register set and a stack space"

 本章将介绍为单个运行进程提供的新抽象 —— 线程 (thread) 

  • 线程是 \textrm{CPU} 调度的一个基本单位(basic unit of CPU scheduling)
  • 一个单独的线程至少有自己的寄存器状态,通常还有自己的栈。

" 在同一进程中可以创建多个线程,并共享代码、地址空间和进程的操作资源 "

❓ 思考:那么问题来了,线程和多线程的区别是什么?

这里有一个经典观点就是:一个程序只有一个执行点,但多线程有多个执行点。

 就让荀彧 (不是苟或!!!) 来给大家举个栗子:

  • 线程:一个程序计数器,用来存放要执行的指令。
  • 多线程:多个程序计数器,每个都用于取指令和执行。

多线程每个线程都类似于独立的线程,所以没有什么太大的区别,它们只有一点区别 ——

 (线程之间共享地址空间,从而能够访问相同的数据)

💡 区别:多线程 共享 地址空间  。因此,单个线程的状态与进程状态非常类似。

线程有一个程序计数器(\textrm{PC}),用于记录程序从哪里获取指令。

 每个线程都有自己的一组用于计算的寄存器,没错就是这么牛啤,人手一套的那种。

所以,如果有两个线程运行在同一处理器上,从运行一个线程 T1 切换到另一个线程 T2 时:

必定会发生 上下文切换 (context switch),我们讲过进程的上下文切换,它是通过 PCB 解决的。 

而线程的上下文切换也是类似于进程的上下文切换的,线程是通过 TCB 解决的。

  • 对于进程:我们将状态保存到进程控制块(PCB )
  • 对于线程:我们要保存每个线程的状态,就需要一个或多个线程控制块(TCB

 但是!与进程相比,线程的上下文切换有 "一点" 不同!

🔍 主要区别:线程的上下文切换,地址空间保持不变(这意味着不需要切换当前使用的页表)。

  • 当 T1\rightarrow T2 时,T1 的寄存器状态被保存,T2 的寄存器状态被恢复,地址空间保持不变。
  • 线程的创建和切换成本是很低的,非常的便宜,因为它们只需要一个栈和存储寄存器。

在多个线程中,每个线程独立运行,不是地址空间中只有一个栈,而是每个线程都有一个栈。

💭 假设:有一个多线程的进程,它有两个线程,结果地址空间看起来不同:

  • 从图中可以观察到,两个栈跨越了进程的地址空间,因此所有位于栈上的变量、参数、返回值和其他能放在栈上的东西,将被放置在线程本地 (thread-loacl) 存储的地方。
  • 多个栈也破坏了地址空间布局的美感,以前,堆和栈可以互不影响的增长,直到空间耗尽。而现在多个栈就没有这么简单了,值得庆幸的是,通常栈不会很大(除非大量使用递归程序)。

为什么要用线程?为什么?因为快!

📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2022.
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

Remzi H. Arpaci-Dusseau and Andrea C. Arpaci-Dusseau, Operating Systems: Three Easy Pieces

A. Silberschatz, P. Galvin, and G. Gagne,

Operating System Concepts, 9th Edition, John Wiley & Sons, Inc., 2014, ISBN 978-1-118-09375-7.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.

这篇关于【OSTEP】并发:线程与多线程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/877754

相关文章

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

Java多线程父线程向子线程传值问题及解决

《Java多线程父线程向子线程传值问题及解决》文章总结了5种解决父子之间数据传递困扰的解决方案,包括ThreadLocal+TaskDecorator、UserUtils、CustomTaskDeco... 目录1 背景2 ThreadLocal+TaskDecorator3 RequestContextH

java父子线程之间实现共享传递数据

《java父子线程之间实现共享传递数据》本文介绍了Java中父子线程间共享传递数据的几种方法,包括ThreadLocal变量、并发集合和内存队列或消息队列,并提醒注意并发安全问题... 目录通过 ThreadLocal 变量共享数据通过并发集合共享数据通过内存队列或消息队列共享数据注意并发安全问题总结在 J

异步线程traceId如何实现传递

《异步线程traceId如何实现传递》文章介绍了如何在异步请求中传递traceId,通过重写ThreadPoolTaskExecutor的方法和实现TaskDecorator接口来增强线程池,确保异步... 目录前言重写ThreadPoolTaskExecutor中方法线程池增强总结前言在日常问题排查中,

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

C语言线程池的常见实现方式详解

《C语言线程池的常见实现方式详解》本文介绍了如何使用C语言实现一个基本的线程池,线程池的实现包括工作线程、任务队列、任务调度、线程池的初始化、任务添加、销毁等步骤,感兴趣的朋友跟随小编一起看看吧... 目录1. 线程池的基本结构2. 线程池的实现步骤3. 线程池的核心数据结构4. 线程池的详细实现4.1 初

Java子线程无法获取Attributes的解决方法(最新推荐)

《Java子线程无法获取Attributes的解决方法(最新推荐)》在Java多线程编程中,子线程无法直接获取主线程设置的Attributes是一个常见问题,本文探讨了这一问题的原因,并提供了两种解决... 目录一、问题原因二、解决方案1. 直接传递数据2. 使用ThreadLocal(适用于线程独立数据)

高并发环境中保持幂等性

在高并发环境中保持幂等性是一项重要的挑战。幂等性指的是无论操作执行多少次,其效果都是相同的。确保操作的幂等性可以避免重复执行带来的副作用。以下是一些保持幂等性的常用方法: 唯一标识符: 请求唯一标识:在每次请求中引入唯一标识符(如 UUID 或者生成的唯一 ID),在处理请求时,系统可以检查这个标识符是否已经处理过,如果是,则忽略重复请求。幂等键(Idempotency Key):客户端在每次