<C#高级编程>第15章笔记
C#中也有函数指针(委托),因此创建起来就可以直接传参给构造函数。。这点比Java简单。。
第15章 线程
多线程的工作方式
一个处理器在某一时刻只能处理一个任务,如果有一个多处理器系统,理论上可以同时执行多个指令。
Windows操作系统表面上可以同时处理多个任务,这个过程称为抢先式多任务 处理(pre-emptive multitasking)。
它是指Windows在某个进程中选择一个线程,该线程允许一小段时间(时间片),之后系统就回收控制权,选择下一个被分派了时间片的线程。这种时间非常短暂,我们可以认为许多事件是同时发生的。
(算法上就是时间片轮 转调度吧……?只是这里还支持优先级……)
线程处理
创建Thread需要一个参数用于指定线程的入口——即线程开始执行的方法。
在C#中就是使用委托。它的签名是:public delegate void ThreadStart()。
由于没有参数,所以必须以其他方式传递信息,例如使用成员字段。
其他常用方法:
- 挂起线程:Suspend()
- 恢复线程:Resume()
- 中断线程:Abort()
- 等待线程终止:Join(),可以指定等待时间。如果过了等待 时间,程序会继续进行。
- 睡眠:Sleep(),令当前正在运行的线程进入睡眠状态。
注意Suspend()和Abort()方法不会立即作用,需要等待一定时间。
线程挂起时,.NET允许其再执行几个指令,直到.NET认为线程可以安全挂起,以保证垃圾回收器执行正确的操作;
线程中断时,将会抛出一个ThreadAbortException。线程真正终止前将执行相应的finally块,这样就保证清理资源,并有机会确保线程正在处理的数据处于有效的状态。
线程的优先级:可以在线程Start前定义它的Priority属性为ThreadPriority的一个枚举值。
同步
通过使用关键字lock来独占对象。
当变量被包装在独占锁中,其他线程就不能访问该变量。Windows会让其他线程处于睡眠状态,直到解锁。
同步问题
死锁:如下就可能造成死锁,在实际应用中要小心在不同的方法调用中使用不同的锁而 造成死锁。
lock(a) { // do sth.. lock(b) { // do sth.. } } |
lock(b) { // do sth.. lock(a) { // do sth.. } } |
竞态:当几个线程试图访问同一个数据,但没有充分考虑其他线程的执行情况时就会发 生竞态。如:
lock(a) { // part 1: do sth.. // using a } // do sth.. <- Current.. lock(a) { // part2: do sth.. // using a }
若线程A执行到Current位置,线程B执行完part1,则A在part2时就会误读到B在part1中改过的数据。