创建线程
创建线程
1 | public class Print |
- 正在执行中的程序实例可被称为一个进程。
- 进程由一个或多个线程组成
- 意味着当运行程序时,始终有一个执行程序代码的主线程
- 当我们构造一个线程时,ThreadStart 或 ParameterizedThreadStart 的实例委托会传给构造函数,我们只需指定在不同线程中运行的方法名,C#编译器后台创建这些对象。
创建线程多种方式
1 | /// <summary> |
暂停线程终止线程
暂停线程、线程等待、终止线程
暂停线程
调用 Thread.Sleep 方法会导致当前线程立即阻止,阻止时间的长度等于传递给 Thread.Sleep 的毫秒数,这样,就会将其时间片中剩余的部分让与另一个线程。 一个线程不能针对另一个线程调用 Thread.Sleep。
1 | public class Print |
线程等待
1 | //修改代码如下 |
- s.Join() 方法,可以实现多个线程间同步执行
终止线程
永久地停止托管线程。一旦线程被中止,它将无法重新启动。
1 | //修改代码如下 |
- s.Abort() 方法,给线程注入了 ThreadAbortException 方法,导致线程被终结
不推荐使用 Abort 方法来关闭线程
原因:该异常可以在任何时候发生,并可能彻底摧毁应用程序
该技术不一定总能终止线程,目标线程可以通过处理该异常并调用 Thread.ResetAbort 方法拒绝被终止
线程状态
线程状态
1 | public class Print |
注意:不要在程序中使用线程终止,以上代码只是演示线程状态
线程优先级
线程优先级
1 | class ThreadSample |
//输出结果
当前线程的优先级:Normal
Running on all cores available
ThreadOne with Highest priority has a count = 1,033,257,770
ThreadTwo with Lowest priority has a count = 778,827,478
Running on a single core
ThreadOne with Highest priority has a count = 11,519,127,196
ThreadTwo with Lowest priority has a count = 48,656,315
前、后台线程
前、后台线程
1 | static void Main(string[] args) |
要点:
1、当在主线程中创建了一个线程,那么该线程的 IsBackground 默认是设置为 FALSE 的。
2、当主线程退出的时候,IsBackground = FALSE 的线程还会继续执行下去,直到线程执行结束。
3、只有 IsBackground = TRUE 的线程才会随着主线程的退出而退出。
4、当初始化一个线程,把 Thread.IsBackground = true 的时候,指示该线程为后台线程。后台线程将会随着主线程的退出而退出。
5、原理:只要所有前台线程都终止后,CLR 就会对每一个活在的后台线程调用 Abort()来彻底终止应用程序。
线程传参
线程传参
1 | public class Print |
死锁、Monitor 类
锁定、死锁、Monitor 类
1 | private static void MonitorLock() { |
lock 本质
private object o = new object();
public void Work()
{
object temp = o;
System.Threading.Monitor.Enter(temp);
try
{
//做一些需要线程同步的工作
}
finally
{
System.Threading.Monitor.Exit(temp);
}
}
提供给 lock 关键字的参数必须为基于引用类型的对象,该对象用来定义锁的范围。
最好避免锁定 public 类型或锁定不受应用程序控制的对象实例
常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:
1)如果实例可以被公共访问,将出现 lock (this) 问题。
2)如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。
3)由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。
最佳做法是定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。