并发编程 - 初识线程

news/2025/1/15 22:16:28/文章来源:https://www.cnblogs.com/hugogoos/p/18673823

01、什么是线程?

要深刻理解什么是线程,就需要了解计算机的发展史,需要了解多任务概念,需要了解进程概念,然后才是线程概念。因为我们主要还是讲解线程,因此这里就不进行展开说其他概念了,有兴趣的可以自行了解下。

简单来说,线程就是操作系统中能够单独执行任务的最小单元。

对于大多数编程语言来说,都有一个或者类似的功能的Main()方法,而该方法中的所有代码也都是按照顺序一行一行的执行,如果要想执行下一行代码那么就必须等待上一行代码执行完成。而线程作为能够单独执行任务的最小单元,因此线程可以使得应用程序的一部分独立于另外一部分而单独运行,这也就意味着我们可以改变程序的常规代码执行顺序,从而达到更复杂的程序控制。

对于一个应用程序来说,要想正常运行至少要有一个线程,通常为主线程,也就是上文中提到的Main()方法,当调用此方法时系统就会自动创建一个主线程。

02、后台线程和前台线程

线程可以分为前台线程和后台线程,两者基本完全相同,唯一区别是前台线程可以在托管执行环境中一直运行,而后台线程不可以。简单来说就是当进程中所有前台进程都停止后,系统会自动停止并关闭该进程内的所有后台线程。

在C#中可以通过Thread.IsBackground查看当前线程类型,也可以通过该属性修改线程类型。默认情况下,通过Thread对象新建并启动的所有线程都是前台线程。

看如下简单示例:

public static void CreateThread()
{Console.WriteLine($"主线程 是否为后台线程:{Thread.CurrentThread.IsBackground}");var thread1 = new Thread(()=> Console.WriteLine("Hello World"));Console.WriteLine($" 线程1 默认为后台线程:{thread1.IsBackground}");thread1.IsBackground = true;Console.WriteLine($" 线程1 设置为后台线程:{thread1.IsBackground}");thread1.Start();
}

执行效果如下:

03、线程的优先级

线程作为操作系统中能够单独执行任务的最小单元,那么当一个进程中有多个线程时,应该先执行那个线程呢?因此线程需要一个标记其执行优先级的属性。

在C#中Thread可以通过Priority来设置线程的优先级,告诉系统应该先执行谁。ThreadPriority有以下5种类型:

  • Lowest: 最低优先级,在所有优先级中最低,在所有线程中可位于最后执行。
  • BelowNormal: 低于正常优先级,在Normal优先级之后,在Lowest优先级之前。
  • Normal: 默认优先级,线程默认的优先级
  • AboveNormal: 高于正常优先级,在Highest优先级的线程之后,在Normal优先级之前。
  • Highest: 最高优先级,在所有优先级中最高,在所有线程中可优先执行。

下面我们做个简单的测试,用来验证优先级不同的导致差异。

class ThreadPriorityTest
{//是否执行,确保一个线程修改此值后,其他线程立刻查看到最新值static volatile bool isRun = true;//确保每个线程都有独立的副本存储计数统计值[ThreadStatic]static long threadCount;//停止运行public void Stop(){isRun = false;}//打印线程名称对应优先级以及计数总数public void Print(){threadCount = 0;while (isRun){threadCount++;}Console.WriteLine($"{Thread.CurrentThread.Name} 优先级为{Thread.CurrentThread.Priority,8} 总执行计数为:{threadCount,-13:N0}");}
}
public static void PriorityTest()
{var threadPriorityTest = new ThreadPriorityTest();//创建3个线程,并设置优先级var thread1 = new Thread(threadPriorityTest.Print){Name = "线程1"};var thread2 = new Thread(threadPriorityTest.Print){Name = "线程2",Priority = ThreadPriority.Lowest};var thread3 = new Thread(threadPriorityTest.Print){Name = "线程3",Priority = ThreadPriority.Highest};//启动3个线程thread1.Start();thread2.Start();thread3.Start();//休眠3秒Thread.Sleep(10000);//停止运行threadPriorityTest.Stop();//等待所有线程完成thread1.Join();thread2.Join();thread3.Join();
}

执行效果如下:

可以发现优先级越高,其执行计数值越大。

其中需要注意的是volatile和ThreadStatic的用法。

在这个多线程示例中我们需要准确的统计不同的线程执行计数,因此正常来说可能需要设置多个变量用来对应存储各自线程的统计计数,很显然这样会导致代码臃肿。因此我们选用了另一种办法,使用ThreadStatic标记一个字段,使得该字段对每个线程都有独立的副本。这样可以做到线程之间不会共享这个字段的值,同时还可以做到多个线程只用这一个字段。

另外对于多线程共享的变量,很可能因为CPU缓存导致多个线程共享的变量不一致问题,因此通过volatile告诉编译器和运行时每次访问该字段时都要直接从内存中读取最新值,以此来保证线程之间的可见性。

04、线程的生命周期

当一个线程被创建后,会经历多个状态,包括未启动、已启动、执行、睡眠、挂起等十个状态,同时Thread类也提供了一些方法,用来控制当前线程状态,比如启动、停止、恢复、中止、挂起以及等待线程等方法。

我们先来看看线程具体有哪些状态:

  • Running(运行)—— 线程已启动,而且没有停止;
  • StopRequested(请求停止) —— 请求停止线程;
  • SuspendRequested(请求挂起) —— 请求线程挂起;
  • Background(后台) —— 线程在后台执行;
  • Unstarted(未启动) —— 还没有在线程上调用 Start()方法;
  • Stopped(停止) —— 线程已完成了其所有的指令,而且已经停止;
  • WaitSleepJoin(等待睡眠连接) —— 通过调用 Wait()、Sleep()或 Join()方法,来暂停线程;
  • Suspended(挂起) —— 线程处于挂起状态;
  • AbortRequested(请求中止) —— Abort()方法已调用,但是线程还没有收到试图终止自己的 System.Threading.ThreadAbortexception,也就是说,线程还没有停止但不久就会停止;
  • Aborted****(中止) —— 线程处于停止状态,但不一定已执行完毕;

下面我们再来看看线程的常用方法。

  • Start(): 启动线程,使其状态变更为Running。
  • Sleep(): 把正在运行的线程暂停一段时间后自动恢复,线程状态保持活跃。
  • Suspend():[已弃用]暂停当前线程的执行,直到调用 Thread.Resume 显式恢复。
  • Resume():[已弃用]恢复一个已被暂停的线程。
  • Interrupt(): 中断处于 WaitSleepJoin 线程状态的线程。
  • Join(): 阻塞调用线程,直到某个线程终止时为止。
  • Abort():[已弃用]终止当前线程。

通过源码可以看到Resume和Suspend方法被弃用的原因。这是因为它们有很多问题和缺陷。使用它可能会导致程序的不稳定、死锁或者资源竞争问题。因此,它已经被标记为废弃,不推荐再使用。

在多线程编程中,通常可以通过合理的同步机制来控制线程的执行。比如,使用上述的 Monitor、Mutex、Event 和 Semaphore 来协调多个线程的行为,确保资源访问的安全和正确性。

:测试方法代码以及示例源码都已经上传至代码库,有兴趣的可以看看。https://gitee.com/hugogoos/Planner

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/869811.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Wgpu图文详解(05)纹理与绑定组

前言 什么是纹理? 纹理是图形渲染中用于增强几何图形视觉效果的一种资源。它是一个二维或三维的数据数组,通常包含颜色信息,但也可以包含其他类型的数据,如法线、高度、环境光遮蔽等。纹理的主要目的是为几何图形的表面提供详细的视觉效果,使其看起来更加真实和复杂。而我…

DeepSeek V3:AI 模型的游戏规则改变者

DeepSeek V3:AI 模型的游戏规则改变者 什么是DeepSeek V3? DeepSeekDeepSeek V3:AI 模型的游戏规则改变者什么是DeepSeek V3? DeepSeek V3是一款具有革命性的混合专家(MoE)模型,总参数达6710亿,每个标记激活370亿参数 。MoE方法允许多个专门模型(即“专家”)在门控网…

Opencv 的下载安装和VisualStudio配置

本文详细介绍了Windows系统下Opencv 的下载安装和VisualStudio配置过程。Opencv 的下载安装和VisualStudio配置 1 opencv-windows的下载 1.1 github直接下载链接(需要外网链接) 最新4.10.0版本的下载链接为: https://github.com/opencv/opencv/releases/download/4.10.0/openc…

G1原理—8.如何优化G1中的YGC

大纲 1.5千QPS的数据报表系统发生性能抖动的优化(停顿时间太小导致新生代上不去) 2.由于产生大量大对象导致系统吞吐量降低的优化(大对象太多频繁Mixed GC) 3.YGC其他相关参数优化之TLAB参数优化 4.YGC其他相关参数优化之RSet、PLAB和大对象的处理优化1.5千QPS的数据报表系统发…

【JavaSecLab靶场】Java综合漏洞平台

免责声明: 请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。在我们平时的网络安全工作中,经常会面对各种各样的挑战。比如,进行定期的漏洞扫描、代码审计,甚至是参与红蓝对抗演练时,发现漏洞后往往需要及时将其修复。 最近,我接触到了一款开…

黑群晖最新安装方式|RR新手

引导盘制作 1、下载最新的黑群晖引导镜像原版链接:wjz304/rr 百度云盘:链接:https://pan.baidu.com/s/12z3v_kVYUDdWNzWBWN_NTQ?pwd=e67k2、将下载好的压缩包解压,得到一个后缀为img的文件。3、使用写盘工具Rufus将镜像文件写到u盘中,点击选择,找到解压好后缀为img的文件…

【Node.js渗透】安装与检测基于Electron的应用程序

免责声明: ⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权!三、说明 传送门:【Node.js开发】Electron 框架介绍,我们已经了解了创建简单Electron应用程序的过程。 本文将…

器件选型---晶振

如何选型晶振,有那些选型注意事项器件选型---晶振 晶振的种类和区别 晶振大体可分为无源晶振和有源晶振两类,其区别如下:无源晶振(crystal,谐振器):内部是两侧贴着金属极板的石英晶体,必须要依赖外部电路才能进行稳定的震动;无源晶振一般会采取下面的接法来与MCU内部的…

Windows自定义变量打开文件或文件夹

前言全局说明Windows 系统自带很多变量,方便使用。 参照系统设置,我们可以自定义一些变量,快速打开文件或文件夹。 例如: 在运行或文件夹地址栏输入 %TEMP% 就能打开对应文件夹一、说明 1.1 环境: Windows 11 家庭版 23H2 22631.37371.2 环境变量位置 用户变量:自定义的文…

鼠标双击连击解决方案

前言 手里的这是第二个才用1年多就出现双击现象的G102了,太不耐操。我算是信了那群广告狗的邪,才又选了这个鼠标。 鼠标双击解决方法主要有以下几种:玄学方法:朝鼠标里哈一口气; 使用软件忽视短暂间隔内的点击行为; 拆鼠标,调整微动; 重买,选光微动+光手轮USB有线鼠标…

2024.1.15闲话

我抄,原!可能是不知道什么学习笔记捏 阶 使得 \(a^x\equiv 1\pmod m\) 的最小正整数 \(x\) 被称为 \(a\) 模 \(m\) 的阶,记作 \(\delta_m(a)\)。由欧拉定理可知, \(a\perp m\) 是 \(\delta_m(a)\) 存在的充要条件。证明 充分性:若 \(a\perp m\),根据欧拉定理,\(x=\varph…

2024中国网络安全产业势能榜优能企业「运营商行业」典型案例展示

运营商作为通信和网络服务的提供者,其安全性直接影响到全球范围内的信息流通与互联网基础设施的稳定。随着5G、云计算等新兴技术的普及,运营商面临着更高的安全压力。本期将展示运营商在加强网络防护、提升数据安全等方面的创新实践,以保障全球信息传输的安全性。 PS:典型案…