Chapter 1 线程基础

线程  即 一个虚拟进程,用于独立运行一个特定程序。

线程会消耗大量的操作系统资源。多个线程共享一个物理处理器将导致操作系统忙于管理这些线程,且无法运行程序。

使用线程通常是一个操作系统任务,试图在单核CPU上并行执行计算任务是没有任何意义的,还会比顺序执行花费更多的时间。

当处理器拥有多核时,让程序不止使用一个处理核心。还需要 组织多个线程间的通信和相互同步。


正在运行中的一个程序实例 可以称为进程,进程由一个或多个线程组成。当运行程序时,始终有一个执行程序代码的主线程。

线程生命周期:


创建线程:

Thread t = new Thread(MethodName);   

 //当我们构造线程时,我们只需制定在不同线程运行的方法名,而编译器会在后台创建这些对象。最后我们在主线程中以通常的方式启动一个线程来运行方法。

t.Start();

这个线程就是独立于主线程的存在 , main 一般就是主线程执行代码!

挂起线程:thread.Suspend 很少用到


暂停线程:

让一个线程等待一段时间而不消耗操作系统资源

在线程调用的方法内部 使用 :

 Thread.Sleep(TimeSpan.FromSecond(2)); //将线程休眠2秒

处于休眠状态时,会占用尽可能少的CPU时间

线程等待:

让程序等待另一个线程中计算的完成。然后在代码中使用该线程的计算结果。

此时不能使用Thread.Sleep 因为 并不知道上一个线程完成计算需要多少时间

Thread t = new Thread(MethodName);

t.Start();

t.Join();

Join()方法,允许我们等待直到线程t完成。当线程t完成时,主线程会继续运行。

通过这种方法可以实现在两个线程间同步执行步骤。

第一个线程会等待另一个线程完成后再继续执行。第一个线程就处于阻塞状态。



线程终止:

Thread t = new Thread(DelayMethodName);

t.Sleep(TimeSpan.FromSeconds(2));

t.Abort();//终止线程

当主线程和单独打印数字线程运行时,使用t.Abort(); 给线程注入了ThreadAbortException方法,导致线程被终结。

目标线程可以通过异常处理机制并调用Thread.ResetAbort方法来拒绝被终止。不推荐Abort()方式终止线程

提供CancellationToken更好结束线程

线程同步: chapter2


检测线程状态:

线程是独立运行的,所以状态在任何时候都可以被改变

Thread.CurrentThread.ThreadStatus.ToString();

//通过Thread.CurrentThread静态属性获得当前Thread对象

t.ThreadStatus.ToString();

Thread对象的ThreadState 是一个枚举对象  只是少数感兴趣的调试方案,永远不应再代码吗中使用线程状态来同步线程活动



线程优先级:

线程优先级决定了该线程可占用多少CPU时间

多核下,同一个计数操作,ThreadPriority.Highest 比 ThreadPriority.Lowest 。

较高优先级通常会计算更多的迭代,但是两个值应该很近。

然而,如果有其他程序占用了所有CPU核心运行负载,结果则截然不不同,优先级低的将计数为0

ProcessorAffinity 选项,让操作系统的所有线程运行在单个CPU核心上。

Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);//所有线程运行在单个CPU核心上

此时,CPU核心大部分时间都在运行高优先级的县线程。


前后台线程:

显式创建的线程都是前台线程,可以通过手动设置为后台线程。thread.IsBackground = true;

程序会等待所有前台线程结束后再结束工作,但是如果只剩下后台线程,则会直接结束工作。

如果 程序定义了一个不会完成的前台线程,主程序并不会正常结束。


向线程传递参数:

传递参数的两种方法:

Thread thread = new Thread(Method);

(1) Thread.Start(Object obj);该方法会接收一个对象,并将该对象传递给线程。

为了应用该方法,在线程中启动的方法Method必须接受object类型单个参数。

(2)lambda 表达式。lambda表达式定义了一个不属于任何类的方法

我们定义了一个方法,该方法使用需要的参数调用了另一个方法,并在另一个线程中运行该方法

Thread thread = new Thread(()=>Method(para));

使用lambda表达式 引用另一个C#对象的方式叫做闭包

当在lambda表达式中使用任何局部变量时,C#会生成一个类,并将该变量作为该类的一个属性

C#会自动帮我们实现这一部分

闭包:在lambda中将局部变量转换成属性。


线程锁:

(1) Lock: 如果锁定了一个对象,需要访问该对象的所有其他线程则会处于阻塞状态,并等待直到该对象接触锁定。

这可能会导致严重的性能问题。

不同线程需要访问某一变量,只需同时锁定某一对象即可,不必锁定需要访问的变量。

(2) Monitor:    Monitor.TryEnter(object) 如果当前线程获取该锁,则为true,否则为false

  Monitor.TryEnter(object,TimeSpan);在指定时间尝试获取指定对象上的排他锁,timespan 值为-1 则表示 指定无期限等待

如果获取到该锁,则返回true,否则返回false

lock 关键字 是 Monitor 类用例的一个语法糖。








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值