• 深入浅出多线程系列之一:简单的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方法可能会被执行两遍.

    参考资料:

    http://www.albahari.com/threading/

    CLR Via C# 3.0

  • 相关阅读:
    AGC 018E.Sightseeing Plan(组合 DP)
    BZOJ.4767.两双手(组合 容斥 DP)
    AGC 001E.BBQ Hard(组合 DP)
    洛谷.3960.列队(线段树/树状数组)
    Codeforces Round #514 (Div. 2)
    10.4 正睿国庆集训测试 青岛
    Codeforces.264E.Roadside Trees(线段树 DP LIS)
    BZOJ.4653.[NOI2016]区间(线段树)
    Ansible安装部署以及常用模块详解
    Linux系统诊断必备技能之二:tcpdump抓包工具详解
  • 原文地址:https://www.cnblogs.com/LoveJenny/p/2049300.html
Copyright © 2020-2023  润新知