c#的线程

1、线程的状态:

1.线程通常有五种状态,创建,就绪,运行、阻塞和死亡状态。
2.阻塞的情况又分为三种:
(1)、等待阻塞:运行的线程执行wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池”中。进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒,wait是object类的方法
(2)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入“锁池”中。
(3)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。sleep是Thread类的方法
1.新建状态(New):新创建了一个线程对象。
2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3. 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4.阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5.死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期

 

 

2、线程创建--就绪---运行

Task task= new Task(()=>{//需要执行的任务})    -------线程创建

task.start()  ------------线程就绪

线程抢占到cpu资源-----线程运行

3、线程阻塞

sleep()和wait()函数的区别:
(1)两者比较的共同之处是:可以使线程进入阻塞状态。
(2)最主要区别是:sleep()方法没有释放锁。而wait()方法释放了锁,使得其他线程可以使用同步控制块或者方法。
(3)sleep()自动唤醒,而wait()需要其他人唤醒,即sleep是自己掌握自己的控制权(几时阻塞几时唤醒),而wait是将控制权交给别的线程!

c#中的线程间通讯:(两个类与3个方法)

AutoResetEvent和ManualResetEvent类(允许不同线程通过互发信号和等待彼此的信号来达到线程同步的目的),WaitOne(),Set(),Reset();

set()与reset()是来改变AutoResetEvent和ManualResetEvent类实体(eventObj)的状态:set()---eventOb进入非终止状态,reset()-----eventObj进入终止状态

 

如果AutoResetEvent和ManualResetEvent类实体的状态为非终止状态时,这线程中有eventObj.WaitOne()则线程就会被阻塞,并监听set()方法,若被调用则线程继续!

AutoResetEvent和ManualResetEvent类的区别:AutoResetEvent在非终止状态下,碰到waitone时会自动调用reset进入终止状态,而ManualResetEvent则不会!

3、线程安全:可见性和有序性

 

 当单线程操作某个对象时,执行顺序如下:
(1) 从主存复制变量到当前工作内存 (read and load)
(2) 执行代码,改变共享变量值 (use and assign)
(3) 用工作内存数据刷新主存相关内容 (store and write)

假设x现在为10,线程a加1,线程b减1,从表面上看,似乎最终x还是为10,但是多线
程情况下会有这种情况发生:
1:线程a从主存读取x副本到工作内存,工作内存中x值为10
2:线程b从主存读取x副本到工作内存,工作内存中x值为10
3:线程a将工作内存中x加1,工作内存中x值为11
4:线程a将x提交主存中,主存中x为11
5:线程b将工作内存中x值减1,工作内存中x值为9
6:线程b将x提交到中主存中,主存中x为9
同样,x有可能为11,每次执行的结果都是不确定的,因为线程的执行顺序是不可预见的。

代码块加锁后的执行过程:

一个线程执行加锁临界区代码过程如下:
1 获得同步锁
2 清空工作内存
3 从主存拷贝变量副本到工作内存
4 对这些变量计算
5 将变量从工作内存写回到主存
6 释放锁 

 阻塞的线程不会去抢占cpu的使用资源,只有就绪状态才会去抢占cpu资源

  线程上下文切换:当CPU从执行一个线程切换到执行另外一个线程(就绪队列)的时候,它需要先存储当前线程的本地的数据的指针,程序指针等,然后载入另一个线程的本地数据,程序指针等,最后才开始执行。这种切换称为“上下文切换”!(更多的是对cpu来说)

  线程从运行状态到非运行状态(非完成)就会发生线程上下文切换;

 上下文切换的具体步骤是(假设当前进程是进程A,要切换到的下一个进程是进程B):

                    1.保存进程A的状态(寄存器和操作系统数据);
                    2.更新PCB中的信息,对进程A的“运行态”做出相应更改;
                    3.将进程A的PCB放入相关状态的队列;
                    4.将进程B的PCB信息改为“运行态”,并执行进程B;
                    5.B执行完后,从队列中取出进程A的PCB,恢复进程A被切换时的上下文,继续执行A。

posted @ 2019-04-02 16:17  xiaoye2019  阅读(100)  评论(0)    收藏  举报