0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

什么是线程

汽车电子技术 来源:程序猿知秋 作者: 程序猿知秋 2023-01-20 15:17 次阅读

基本概念

线程

  • 被定义为程序的执行路径,也叫执行单元
  • 线程是轻量级进程;使用线程节省了 CPU 周期的浪费,同时提高了应用程序的效率

进程

  • 是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程
  • 一个进程可以包括一个或多个线程, 注:至少得有一个线程
  • 进程之间是相对独立的,一个进程无法访问另一个进程的数据

查看当前系统中的进程

微信截图_20230105161930.png

打开任务管理器,查看当前运行的进程

编辑

查看当前系统中的线程

在任务管理器里面查询当前总共运行的线程数

****微信截图_20230105161930.png

编辑****

并行与串行(异步与同步)

  • 并行(异步): 多个线程同时执行任务
    • 举例:小明在烧开水的同时去洗菜了
  • 串行(同步): 一个任务执行完后才能执行下一个
    • 举例:小明在烧开水,等开水烧开后再去洗菜

线程的生命周期

  • 新建 :当线程实例被创建但 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 源码,可以看到它其实是一个委托

**微信截图_20230105161930.png

编辑**

  • 如果要向子线程中传递参数则需要使用: ParameterizedThreadStart
  • 注意:ParameterizedThreadStart委托的参数类型必须是Object的
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的,一个CPU在同一时刻只能运行一个线程,但是多个CPU在同一时刻就可以运行多个线程。

  • 线程的最大并行数量上限是CPU核心的数量,但是,往往电脑运行的线程的数量远大于CPU核心的数量,所以还是需要CPU时间片的切换

  • CPU运行速度太快,硬件处理速度跟不上,所以操作系统进行分 ** 时间片

    管理** 。这样,从宏观角度来说是多线程并发的,因为CPU速度太快,察觉不到,看起来是同一时刻执行了不同的操作

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10446

    浏览量

    206572
  • 应用程序
    +关注

    关注

    37

    文章

    3136

    浏览量

    56400
  • 线程
    +关注

    关注

    0

    文章

    489

    浏览量

    19498
收藏 人收藏

    评论

    相关推荐

    线程编程之Linux线程编程

    9.2 Linux线程编程 9.2.1 线程基本编程 这里要讲的线程相关操作都是用户空间中的线程的操作。在Linux中,一般pthread线程
    发表于 10-18 15:55 3次下载

    线程好还是单线程好?单线程和多线程的区别 优缺点分析

    摘要:如今单线程与多线程已经得到普遍运用,那么到底多线程好还是单线程好呢?单线程和多线程的区别又
    发表于 12-08 09:33 8w次阅读

    线程的实现方式,四线程和八线程的区别介绍

    摘要:线程是程序执行流的最小单元。四线程和八线程线程的两种表现形式,下面来看看它们之间的区别以及线程的实现方式。
    发表于 12-08 14:31 1.1w次阅读

    处理器6核12线程和8核16线程区别大吗

    很多网友问处理器6核12线程和8核16线程的区别是什么,首先我们来了解下什么是6核12线程和8核16线程
    发表于 01-01 17:44 5.2w次阅读

    MFC多线程线程同步

    MFC中有两类线程,分别称之为工作者线程和用户界面线程。二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。
    发表于 06-01 17:03 0次下载

    什么是线程线程池中线程实现复用的原理

    一般建议自定义线程工厂,构建线程的时候设置线程的名称,这样就在查日志的时候就方便知道是哪个线程执行的代码。
    发表于 01-29 13:44 1342次阅读

    线程线程

    线程池通常用于服务器应用程序。 每个传入请求都将分配给线程池中的一个线程,因此可以异步处理请求,而不会占用主线程,也不会延迟后续请求的处理
    的头像 发表于 02-28 09:53 462次阅读
    多<b class='flag-5'>线程</b>之<b class='flag-5'>线程</b>池

    详解Linux线程线程与异步编程、协程与异步

    协程不是系统级线程,很多时候协程被称为“轻量级线程”、“微线程”、“纤程(fiber)”等。简单来说可以认为协程是线程里不同的函数,这些函数之间可以相互快速切换。
    的头像 发表于 03-16 15:49 654次阅读

    什么是线程安全?如何理解线程安全?

    在多线程编程中,线程安全是必须要考虑的因素。
    的头像 发表于 05-30 14:33 1510次阅读
    什么是<b class='flag-5'>线程</b>安全?如何理解<b class='flag-5'>线程</b>安全?

    核心线程数和最大线程数区别

    核心线程数和最大线程数区别 核心线程数是线程池中一直存在的线程数,不会被回收。最大线程数是
    的头像 发表于 06-01 09:33 6090次阅读

    线程池的线程怎么释放

    线程分组看,pool名开头线程占616条,而且waiting状态也是616条,这个点就非常可疑了,我断定就是这个pool开头线程池导致的问题。我们先排查为何这个线程池中会有600+的
    发表于 07-31 10:49 1234次阅读
    <b class='flag-5'>线程</b>池的<b class='flag-5'>线程</b>怎么释放

    Linux线程线程与异步编程、协程与异步介绍

    协程不是系统级线程,很多时候协程被称为“轻量级线程”、“微线程”、“纤程(fiber)”等。简单来说可以认为协程是线程里不同的函数,这些函数之间可以相互快速切换。 协程和用户态
    的头像 发表于 11-11 11:35 425次阅读
    Linux<b class='flag-5'>线程</b>、<b class='flag-5'>线程</b>与异步编程、协程与异步介绍

    核心线程数和最大线程数怎么设置

    核心线程数和最大线程数是Java线程池中重要的参数,用来控制线程池中线程的数量和行为。正确地设置这两个参数可以优化系统的性能和资源利用率。本
    的头像 发表于 12-01 13:50 4110次阅读

    线程池的创建方式有几种

    线程池是一种用于管理和调度线程的技术,能够有效地提高系统的性能和资源利用率。它通过预先创建一组线程并维护一个工作队列,将任务提交给线程池来处理,从而减少
    的头像 发表于 12-04 16:52 413次阅读

    什么是动态线程池?动态线程池的简单实现思路

    因此,动态可监控线程池一种针对以上痛点开发的线程池管理工具。主要可实现功能有:提供对 Spring 应用内线程池实例的全局管控、应用运行时动态变更线程池参数以及
    的头像 发表于 02-28 10:42 181次阅读