如果我们想泡壶茶喝,顺序(串行)流程:洗净水壶,灌上凉水,放在火上,坐待水开;水开了之后,找茶叶,洗茶壶茶杯,泡茶喝。程序常规执行顺序也是一样,一个任务是在前一个任务完成之后才执行。而泡茶也可以采用并行流程洗好水壶,灌上凉水,放在火上;在等待水开的时间里,洗茶壶、洗茶杯、拿茶叶;等水开了,泡茶喝。这在数学世界里就是华罗庚的统筹学原理。而在编程世界里叫做线程技术。线程技术就是指开发架构将应用程序的一部分分离为“线程”,使线程与程序其余部分执行步骤不一致。我们可以看到线程的使用可以节省时间,提高资源利用率。
这里我们需要理解几个概念
操作系统:软件运行平台。这里与操作系统有关的就是系统线程(系统任务管理器)。
软件:是包含程序的有机集合体,程序是软件的必要元素。任何软件都有可运行的程序
程序:指令(语句)序列的集合。。每个指令若干代码编写的。
进程:系统为应用程序分配内存和其他资源(线程)的物理隔离。
图 1-1 演示了进程和线程之间的关系
什么是线程?
线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。
注:线程实际上不包括指令只是指出了当前和将来指令可能要使用的路径。
什么是多线程?
多线程是指程序中包含多个执行流,即在同一个程序中可以同时运行多个线程执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
简而言之多线程就是多任务并发执行。
注:这里任务是一个业务逻辑的概念,在应用程序中指的是具体的方法或函数。
多线程的好处:
提高CPU的利用率。当一个线程必须等待的时候,CPU不用闲置可以执行其他线程。
节省时间:并行执行省去了等待时间。但需要注意的时候可能多出了线程切换时间。
多线程的不利方面:
占用内存。
线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;。比如一个银行账户有100元,如果A先生和他的夫人在不同的ATM取款机同时取100元,这时候程序就发生了错误。
多线程需要协调和管理,所以需要CPU时间跟踪线程;
线程太多会导致控制太复杂,最终可能造成很多Bug;
线程一些概念与.NET的Thread类
|
名称 |
说明 |
|
获取当前正在运行的线程。 |
|
|
获取一个值,该值指示当前线程的执行状态。 |
|
|
获取或设置一个值,该值指示某个线程是否为后台线程。 |
|
|
获取一个值,该值指示线程是否属于托管线程池。 |
|
|
获取当前托管线程的唯一标识符。 |
|
|
获取或设置线程的名称。 |
|
|
获取或设置一个值,该值指示线程的调度优先级。 |
|
|
获取一个值,该值包含当前线程的状态。 |
线程的方法操作和生存期状态
下表显示了导致状态更改的操作。
操作 |
ThreadState |
在公共语言运行时中创建线程。 |
Unstarted |
线程调用 Start |
Unstarted |
线程开始运行。 |
Running |
线程调用 Sleep |
WaitSleepJoin |
线程对另一个对象调用 Wait。 |
WaitSleepJoin |
线程对另一个线程调用 Join。 |
WaitSleepJoin |
另一个线程调用 Interrupt |
Running |
另一个线程调用 Suspend |
SuspendRequested |
线程响应 Suspend 请求。 |
Suspended |
另一个线程调用 Resume |
Running |
另一个线程调用 Abort |
AbortRequested |
线程响应 Abort 请求。 |
Stopped |
线程终止。 |
Stopped |
时间片
操作系统为每个应用程序都授权了一个时间段,让应用程序在这个时间段运行,之后就中断该应用程序的执行,让另一个应用程序执行。这个进程执行的时间段就叫做时间片或时间段。
线程的中断
中断是一种机制,它能够使CPU指令的正常顺序执行转向计算机内存中的其他地方,而不需要知道目前正在执行什么程序。
如何判断是什么时候该中断?
时间片
有谁来进行线程的中断?
系统线程负责应用程序线程的调度。
Windows的特殊函数,即中断的处理程序。
如何进行中断
在当前的线程的执行序列(指令集)放置中断指令。
如何判断在此线程中断后执行的下个线程是什么?
此线程中断,就会被移到队列末尾,然后执行队列较前面的线程。有点像队列。
在线程中断之前需要做些什么?
中断处理程序将这个线程状态存储在TLS中。队列中保存TLS在内存的地址。
线程的TLS:寄存器,堆栈指针,调度信息,内存中的地址空间和其他资源使用信息。
线程的睡眠和叫醒
为什么线程需要睡眠?
程序可以将自己的执行的时间让给另一个线程,以等待某些外部资源,可能线程执行多次执行多次,资源仍旧无法使用。(比如对交换数据的进行处理,数据可能很长时间没有过来,这时候就需要等待)。这时候我们就希望使线程推出队列较长的时间。这样处理器就不必在从一个线程到另一个线程的来回切换中浪费时间。而线程自动退出队列的这段时间就叫做的睡眠。
线程如何睡眠和叫醒?
睡眠:调用睡眠指令
叫醒:在睡眠队列中插入时钟中断。
线程的终止
如何终止线程?
通过向系统线程发出一个请求(线程)显式停止线程执行。线程不能自我终止。
线程终止后会怎么样?
TLS释放内存。但进程中的数据仍然存在。
线程的属性
线程的名称(Name)
线程的优先级(Priority)
线程调度优先级是由操作系统的系统进程来设置
调度优先级
系统管理员才能设置15级以上的优先级。
实时运行的项目
设备驱动程序,文件系统,输入输出设备等进程
如何管理优先级
通过资源管理器和编程手段
第三章线程使用
同步
同步的含义
同步:在任意时刻只允许一个线程访问资源的现象称作同步。
为什么需要同步
- 避免竞争条件
- 确保线程安全
如何确保线程安全
l 同步代码中重要的部分
l 使对象不可改变
l 使用线程安全包装器
同步重要代码段
重要代码段:程序中多个线程可以在同一时间访问以更新对象状态的一段代码。
一个用户线程执行完毕才允许另一个用户执行
通知数据更新
判断数据资源是否符合操作条件
.NET对同步的支持
Monitor(监视器):锁定重要代码段。确保任意时刻只能有一个线程访问重要代码段
Mutex(互斥体):锁定资源。只允许一个线程访问在进程中的共享资源。