先看一个简单的例子(从网上扒下来的。)
using System; using System.Threading; // Simple threading scenario: Start a static method running // on a second thread. public class ThreadExample { // The ThreadProc method is called when the thread starts. // It loops ten times, writing to the console and yielding // the rest of its time slice each time, and then ends. public static void ThreadProc() { for (int i = 0; i < 10; i++) { Console.WriteLine("ThreadProc: {0}", i); // Yield the rest of the time slice. Thread.Sleep(1000); } } public static void Main() { Console.WriteLine("Main thread: Start a second thread."); // The constructor for the Thread class requires a ThreadStart // delegate that represents the method to be executed on the // thread. C# simplifies the creation of this delegate. Thread t = new Thread(new ThreadStart(ThreadProc)); // Start ThreadProc. On a uniprocessor, the thread does not get // any processor time until the main thread yields. Uncomment // the Thread.Sleep that follows t.Start() to see the difference. t.Start(); //Thread.Sleep(0); for (int i = 0; i < 4; i++) { Console.WriteLine("Main thread: Do some work."); Thread.Sleep(1000); } Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends."); if (t.ThreadState == ThreadState.Running) { t.Join(); } Console.WriteLine("Main thread: ThreadProc.Join has returned. Press Enter to end program."); Console.ReadLine(); } }
这是一个很简单的小例子。不过能说明多线程工作的原理(本人刚涉及多线程,如有不对,请各位看官跟贴指出哈~~~~)。
首先呢,还是结合当年大学里学的操作系统原理,讲一下基础知识。
1)进程和线程
简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 进程是程序向操作系统申请资源的基本单位。而线程是不能向操作系统申请资源的,但是他可以和其他线程一起利用父进程申请到的部分资源。正因为要和其他线程一起使用资源,所以必然会发生冲突。这里为了解决冲突呢,我们一般是会对资源进行加锁操作,控制同步基元等(这是后话,这里着重讲解线程的基础知识)。线程是进程中执行运算的基本单位。
2)创建新线程
线程的创建和销毁都可以在另一个线程中执行操作。比如,UI线程,你们都懂的哈~~~~嘎嘎
3)多线程的执行
创建了多线程程序以后,很多人会思考多线程的执行方式。在这里,我依旧援引操作系统原理那门课的理论(哈哈~别骂我哈,各位看官。我们大学的操作系统原理是全国有名的,那位老教授爷爷给我们讲课的那本书都是他自己写的,很猛的)。CPU其实是这么工作的,系统当前维护的所有进程中的线程,默认情况下都是有相同的获得CPU运行时间的权力。这里要解释下,什么叫CPU运行时间?咳咳,其实呢,我们看到的某个程序一直在运行。比如是你在windows操作系统下复制一个文件,你会看到有一个动画,好像一页一页的纸从一个文件夹到另一个文件夹。对,我说的就是那个。那个你看上去是一连贯的动作,其实他不是连贯的,只是现代的计算机的硬件设备实在太先进的,CPU处理速度太快。人类的肉眼根本看不出来其中的间隙。那么我来帮大家解释下这个过程。其实操作系统的所有线程都在CPU上跑(一般情况下有几十上百,甚至上千个线程,那是很正常的)。这些线程,都是要占用CPU,这个不必我说了吧(当然还占用其他系统资源,比如内存!)。那么,这么多线程同时占用CPU,怎么办呢?于是操作系统就把CPU的占用划分成很多的时间片。每个时间片里面执行一个线程。这个时间片一过,那么刚执行的线程就移出CPU的执行,下一个线程进入。如此往返,确保系统维护的所有线程都能被分配到CPU。这个就是CPU时间片(也称时间轮)。(当然,刚说的线程的交替获得CPU时间片的过程中,还涉及到保护现场等的复杂操作,有兴趣的同学可以仔细阅读下操作系统原理。)刚说了,默认情况下系统中各线程获得CPU的时间片的概率是相同的,不过呢,我们可以改变某个线程的权值,提高他的执行优先级。那么这个线程就比其他线程具有更大的获得CPU执行时间片的概率了。额,貌似有点讲深了。嗯,我们先不管各线程的权值不一样的情况,默认各线程的权值都相同,就是获得CPU时间轮的概率相同。那么这个情况下,各个线程是一同在CPU上跑的,一个线程跑的时间片到了,就移出CPU,下个线程进来,各线程交替获得CPU。看上面的程序程序执行结果就能看出来了。不过,如果我把主线程的sleep那段代码注销掉,会怎么样呢?那么理论上是会先把主线程的代码全部执行结束,然后去执行新线程的代码。可是多执行几次看看结果。却发现,不完全是这样的,执行的结果,会不一样。微软的解释是这样的:各位童鞋,这个是正常的情况,相同的多线程程序是会出现一些小的不同的执行结果的。谁也不能保证多线程的程序,执行结果是怎么样的,结果是不可预测的。所以虽然,现代程序有很都需要多线程的处理,但是,我们建议,不到万不得已,请不要使用多线程。因为极容易导致一些不可预知的,且灾难性的后果。