深入浅出多线程系列之一:简单的Thread

简介:

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 ;
            }
        }
复制代码

这种现象就叫做线程安全,或者说缺少线程安全。后续文章会慢慢介绍。

 

谢谢楼下的chenlulouis同学的建议:

下面做下解释: 

虽然new Thread(tt.Go) 和tt.Go方法都共享tt的done字段,但是两个线程可能都通过了if判断,

所以Console.WriteLine方法可能会被执行两遍.






本文转自LoveJenny博客园博客,原文链接:http://www.cnblogs.com/LoveJenny/archive/2011/05/21/2049300.html,如需转载请自行联系原作者
目录
相关文章
|
2月前
|
Java 中间件 API
【C/C++ 线程 】深入浅出:理解 std::thread 的局限性
【C/C++ 线程 】深入浅出:理解 std::thread 的局限性
52 2
|
3月前
|
监控 安全 Java
多线程Thread(初阶一:认识线程)
多线程Thread(初阶一:认识线程)
40 0
|
5月前
|
人工智能 自然语言处理 Linux
进程(process) vs 线程(Thread)
本文主要介绍了进程和线程的基本概念、区别以及操作系统如何调度线程的方式。同时,还介绍了线程锁的核心原理和实现方式。在多线程编程中,理解进程和线程的概念以及线程锁的使用,对于保证程序的安全性和性能非常重要。
48 0
|
5月前
|
Java
多线程与并发,Java中介绍一下Thread类和Runnable接口的区别。
多线程与并发,Java中介绍一下Thread类和Runnable接口的区别。
33 1
|
2月前
|
存储 前端开发 算法
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析(一)
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析
56 0
|
2月前
|
存储 并行计算 Java
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析(二)
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析
70 0
|
2天前
|
Java API 调度
【Java多线程】Thread类的基本用法
【Java多线程】Thread类的基本用法
5 0
|
4天前
|
算法 安全 调度
【C++入门到精通】 线程库 | thread类 C++11 [ C++入门 ]
【C++入门到精通】 线程库 | thread类 C++11 [ C++入门 ]
13 1
|
9天前
|
存储 机器学习/深度学习 C++
thread(线程)
**Lua中的协同程序(coroutine)类似线程,有独立栈和局部变量,但它们不能并行,只能单次运行,通过挂起切换。** \n\n**Userdata是自定义数据类型,允许存储C/C++的任意数据到Lua,常用于struct和指针。**
|
5月前
面试官:除了继承Thread类和实现Runnable接口,你知道使用Callable接口的方式来创建线程吗?
面试官:除了继承Thread类和实现Runnable接口,你知道使用Callable接口的方式来创建线程吗?
20 0
面试官:除了继承Thread类和实现Runnable接口,你知道使用Callable接口的方式来创建线程吗?