基本概念
线程
- 被定义为程序的执行路径,也叫执行单元
- 线程是轻量级进程;使用线程节省了 CPU 周期的浪费,同时提高了应用程序的效率
进程
- 是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程
- 一个进程可以包括一个或多个线程, 注:至少得有一个线程
- 进程之间是相对独立的,一个进程无法访问另一个进程的数据
查看当前系统中的进程
打开任务管理器,查看当前运行的进程
编辑
查看当前系统中的线程
在任务管理器里面查询当前总共运行的线程数
****
编辑****
并行与串行(异步与同步)
- 并行(异步): 多个线程同时执行任务
- 举例:小明在烧开水的同时去洗菜了
- 串行(同步): 一个任务执行完后才能执行下一个
- 举例:小明在烧开水,等开水烧开后再去洗菜
线程的生命周期
- 新建 :当线程实例被创建但 Start 方法未被调用时的状况
- 就绪 :当线程准备好运行并等待 CPU 调度
- 不可运行 :下面的几种情况下线程是不可运行的:
- 已经调用 Sleep 方法
- 已经调用 Wait 方法
- 通过 I/O 操作阻塞
- 死亡状态 :当线程已完成执行或已中止时的状况
主线程
- 一个进程可以包含若干个线程,在进程入口执行的 第一个线程被视为这个进程的主线程 。
- 在 C# 中,都是以Main()方法作为入口的,当调用此方法时系统就会自动创建一个主线程。
- 在 C# 中,System.Threading.Thread 类用于线程的工作。它允许创建并访问多线程应用程序中的单个线程
- 可以使用 Thread 类的 CurrentThread 属性访问线程。
举例:主线程执行
internal class ThreadTest
{
static void Main(string[] args)
{
Thread th = Thread.CurrentThread;
th.Name = "MainThread";
Console.WriteLine("线程ID是:{0},线程名称是:{1}", th.ManagedThreadId, th.Name);
}
}
输出结果
线程ID是:1,线程名称是:MainThread
**多线程的创建与管理 **
创建
- 线程是通过扩展 Thread 类创建的,然后在构造方法中传入委托对象。扩展的 Thread 类调用 Start() 方法来开始子线程的执行
- **子线程不需要传参使用 **ThreadStart
internal class ThreadTest
{
static void Main(string[] args)
{
// 创建两个子线程
Thread t1 = new Thread(new ThreadStart(PrintStr));
Thread t2 = new Thread(new ThreadStart(PrintStr));
t1.Start();
t2.Start();
}
private static void PrintStr()
{
Thread th = Thread.CurrentThread;
Console.WriteLine("线程ID是:{0}", th.ManagedThreadId);
}
}
输出结果
线程ID是:7
线程ID是:6
通过ThreadStart 源码,可以看到它其实是一个委托
**
编辑**
internal class ThreadTest
{
static void Main(string[] args)
{
// 创建两个子线程
Thread t1 = new Thread(new ParameterizedThreadStart(PrintStrParam));
Thread t2 = new Thread(new ParameterizedThreadStart(PrintStrParam));
t1.Start("我是有参数1");
t2.Start("我是有参数2");
}
private static void PrintStrParam(Object obj)
{
Thread th = Thread.CurrentThread;
Console.WriteLine("线程ID是:{0},参数是:{1}", th.ManagedThreadId,obj);
}
}
输出结果
线程ID是:6,参数是:我是有参数1
线程ID是:7,参数是:我是有参数2
线程的管理与销毁
- Thread 类提供了各种管理线程的方法,下面演示sleep() 方法的使用,用于在一个特定的时间暂停线程
- Abort() 方法用于销毁线程;通过抛出 threadabortexception 在运行时中止线程。这个异常不能被捕获,如果有 finally 块,控制会被送至 finally 块。 注:这个方法被标记过时了,虽然依旧可以使用,但推荐使用 CancellationToken 来代替
internal class ThreadTest
{
static void Main(string[] args)
{
// 创建两个子线程
Thread t1 = new Thread(new ThreadStart(printSleep));
t1.Start();
// 主线程睡眠 1 秒
Thread.Sleep(1000);
// 销毁线程
try
{
t1.Abort();
}
catch (ThreadAbortException e)
{
Console.WriteLine("进catch了吗???");
}
finally
{
Console.WriteLine("进finally了吗???");
}
}
private static void printSleep()
{
for (int i = 0; i < 10; i++)
{
// 睡眠 500 毫秒
Thread.Sleep(500);
Console.WriteLine("输出数字:{0}", i);
}
}
}
输出结果
输出数字:0
Unhandled exception. 输出数字:1
System.PlatformNotSupportedException: Thread abort is not supported on this platform.
输出数字:2
进finally了吗???
线程同步与锁
- 所谓同步:是指在某一时刻只有一个线程可以访问变量。
- 如果不能确保对变量的访问是同步的,就会产生错误。比如:两个人同时卖一个仓库中的同种 手机,如果不控制就可能出现 超卖现象 (即卖出的大于库存的)
- c#为同步访问变量提供了一个非常简单的方式,即使用c#语言的关键字 **Lock**,它可以把一段代码定义为互斥段,互斥段在一个时刻内只允许一个线程进入执行
lock
块语法:
- 需要注意,传给**
lock
块**的参数不能是值类型和string
类型,必须是除了string
外的引用类型,而且这个引用类型对象必须是所有线程都能访问到的,否则锁不住。 - 如果你想保护一个类的实例,一般地,你可以使用this;
- 如果你想保护一个静态变量(如互斥代码段在一个静态方法内部),一般使用类名就可以了
- 也可以单独创建一个
object
对象来作为指定的锁对象
语法如下:
lock(expression)
{
// 代码逻辑
}
加锁前案例
internal class ThreadTest
{
static void Main(string[] args)
{
PhoneSale phone=new PhoneSale();
// 创建两个子线程
Thread t1 = new Thread(new ThreadStart(phone.SalePhone));
Thread t2 = new Thread(new ThreadStart(phone.SalePhone));
t1.Start();
t2.Start();
}
}
public class PhoneSale
{
// 数量
private int num = 1;
public void SalePhone()
{
if (num > 0)
{
Thread.Sleep(100);
num--;
Console.WriteLine("卖出一部手机,还剩下 {0} 个",num);
}
else
{
Console.WriteLine("卖完了....");
}
}
}
输出结果
卖出一部手机,还剩下 0 个
卖出一部手机,还剩下 -1 个
**加锁后案例
**
internal class ThreadTest
{
static void Main(string[] args)
{
PhoneSale phone=new PhoneSale();
// 创建两个子线程
Thread t1 = new Thread(new ThreadStart(phone.SalePhone));
Thread t2 = new Thread(new ThreadStart(phone.SalePhone));
t1.Start();
t2.Start();
}
}
public class PhoneSale
{
// 数量
private int num = 1;
public void SalePhone()
{
lock (this)
{
if (num > 0)
{
Thread.Sleep(100);
num--;
Console.WriteLine("卖出一部手机,还剩下 {0} 个", num);
}
else
{
Console.WriteLine("卖完了....");
}
}
}
}
输出结果
卖出一部手机,还剩下 0 个
卖完了....
多线程的优缺点
优点
- 可以同时完成多个任务,使程序的响应速度更快
- 多线程技术解决了多部分代码同时执行的需求,能够更好的利用cpu的资源
- 可以设置每个任务的优先级以优化程序性能
缺点
- 线程需要占用内存,线程越多,占用内存也越多
- 多线程需要协调和管理,所以需要占用CPU时间以便跟踪线程
- 线程之间对共享资源的访问会相互影响,必须解决争用共享资源的问题
- 线程太多会导致控制太复杂
为什么程序可以多线程执行呢? 程序中的多线程与CPU的多线程有什么关系?
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
-
cpu
+关注
关注
68文章
10854浏览量
211578 -
应用程序
+关注
关注
37文章
3265浏览量
57677 -
线程
+关注
关注
0文章
504浏览量
19675
发布评论请先 登录
相关推荐
Java的线程课程
线程的概念线程其实是控制线程(Thread of control)的简写。 控制线程就是程序运行时的路径,是在一个程序中与其它控制线程无关的
发表于 04-10 15:58
•0次下载
JAVA线程实验
实验11 线程一、实验目的 1. 线程的概念、线程的生命周期。2. 多线程的编程:继承Thread类与使用Runnable接口。3. 使用多
发表于 09-23 19:04
•1191次阅读
多线程编程之Linux线程编程
9.2 Linux线程编程 9.2.1 线程基本编程 这里要讲的线程相关操作都是用户空间中的线程的操作。在Linux中,一般pthread线程
发表于 10-18 15:55
•3次下载
多线程好还是单线程好?单线程和多线程的区别 优缺点分析
摘要:如今单线程与多线程已经得到普遍运用,那么到底多线程好还是单线程好呢?单线程和多线程的区别又
发表于 12-08 09:33
•8.1w次阅读
线程的实现方式,四线程和八线程的区别介绍
摘要:线程是程序执行流的最小单元。四线程和八线程是线程的两种表现形式,下面来看看它们之间的区别以及线程的实现方式。
发表于 12-08 14:31
•1.2w次阅读
MFC多线程及线程同步
MFC中有两类线程,分别称之为工作者线程和用户界面线程。二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。
发表于 06-01 17:03
•0次下载
线程池的线程怎么释放
从线程分组看,pool名开头线程占616条,而且waiting状态也是616条,这个点就非常可疑了,我断定就是这个pool开头线程池导致的问题。我们先排查为何这个线程池中会有600+的
发表于 07-31 10:49
•2274次阅读
线程池基本概念与原理
一、线程池基本概念与原理 1.1 线程池概念及优势 C++线程池简介 线程池是一种并发编程技术,它能有效地管理并发的线程、减少资源占用和提高
核心线程数和最大线程数怎么设置
核心线程数和最大线程数是Java线程池中重要的参数,用来控制线程池中线程的数量和行为。正确地设置这两个参数可以优化系统的性能和资源利用率。本
redis多线程还能保证线程安全吗
Redis是一种使用C语言编写的高性能键值存储系统,它是单线程的,因为使用了多路复用的方式来处理并发请求。这样的实现方式带来了很好的性能,但同时也引发了一些线程安全方面的问题。 在Redis中,由于
CPU线程和程序线程的区别
CPU的线程与程序的线程在概念、作用、实现方式以及性能影响等方面存在显著差异。以下是对两者区别的详细阐述,旨在深入探讨这一技术话题。
评论