CLR和操作系统会自动的为应用程序创建一个线程,这个线程叫做主线程(main Thread)
如果要创建一个新的线程,可以使用Thread类。下面是一个简单的例子:
class ThreadTest{ static void Main() { Thread t = new Thread (WriteY); // 创建一个新的线程来执行WriteY方法 t.Start(); // 开始运行 WriteY() //在主线程上模拟的做些事情. for ( int i = 0 ; i < 1000 ; i ++ ) Console.Write ( " x " ); } static void WriteY() { for ( int i = 0 ; i < 1000 ; i ++ ) Console.Write ( " y " ); }} 首先创建了一个线程来执行WriteY方法,然后调用Start()来启动创建的线程,接着在主线程中用for循环输出“x”。
很容易就知道答案:例如XXXXYYYYXXXXXYYYYYXXXXYYYYYYYYYYYYYYYYYYYXXXXXXXXXXXXXXX
X和y间隔的出现。
一旦线程启动了,线程的IsAlive属性在线程结束前就会返回True,当传递给线程的构造函数中的委托执行完毕,线程就结束了,一旦线程结束了,线程是不可能再重新启动的。
CLR为每一个线程分配独立的内存栈,这样就可以保证局部变量隔离。下面是使用局部变量的例子。
class ThreadTest { bool done; public static void Main() { ThreadTest tt = new ThreadTest(); new Thread(tt.Go).Start(); tt.Go(); } void Go() { if ( ! done) { done = true ; Console.WriteLine( " Done " ); } } } 因为new Thread(tt.Go) 和tt.Go方法都共享tt的done字段。
所以Console.WriteLine("Done")会且只会被执行一变。
我们修改下上面的代码,修改后如下:
class ThreadTest { static bool done; //静态变量被所有的线程共享 public static void Main() { new Thread(Go).Start(); Go(); } static void Go() { if ( ! done) { done = true ; Console.WriteLine( " Done " ); } } } 问题来了,Console.WriteLine会被执行几遍?
有些同学会说一遍,有些同学会说两遍,其实答案很简单:有时候一遍,有时候两遍。
因为静态变量会被所有线程共享,
执行一遍的就不解释了,比较简单。
执行两遍:线程A执行到if(!done) 此时done为false。所以通过if判断,在同时线程B也执行到了if(!done)此时done也为false,所以也通过了判断。
如果你把上面的Go代码调整到下面的样子,出现两次的概率就会变大很多。
static void Go() { if ( ! done) { // 两个线程都到了这里 Console.WriteLine( " Done " ); done = true ; } } 这种现象就叫做线程安全,或者说缺少线程安全。后续文章会慢慢介绍。