zoukankan      html  css  js  c++  java
  • C#深入多线程

    主线程:

    th = Thread.CurrentThread;   //现在的线程为主线程
    th.Name = "MainThread";     //set线程名字:主线程本身没有名字
    thread1.Text += th.Name;    //get线程名字

    创建线程:

    //创建线程
    ThreadStart thread_action = new ThreadStart(ThreadAction);      //方法/写法一
    Thread new_thread = new Thread(thread_action);
    new_thread.Start();
    
    new Thread(ThreadAction).Start();   //方法二:自动转换成ThreadStart
    new Thread(() => ThreadAction());   //方法三:使用lambda表达式
    
    public static void ThreadAction()
    {
        Console.WriteLine("New Thread will do.");
    }

    创建带参数的线程:

    ParameterizedThreadStart parameterizedThreadStart = new ParameterizedThreadStart(testBoy);
    Thread new_thread = new Thread(parameterizedThreadStart);
    new_thread.Start("hello");  //这样只能指定一个参数
    
    new Thread(testBoy).Start("hello");
    new Thread(() => testBoy("hello baby")).Start();    //这start就不要写参数了,不然会抛出异常的;这样写的好处是可以有多个参数
    
    static void testBoy(object girl)
    {
        Console.WriteLine(girl);
    }

    暂停线程:

    Thread.Sleep(1000);     //让当前线程sleep,单位ms

    等待线程(等待与暂停不一样):

    等待:当前线程,等待调用Join的线程执行完毕。暂停:暂停调用Sleep的线程。

    销毁线程(在定义线程引用thread的地方,可以调用thread.Abort方法):

    thread.Abort();      //用Thread.ResetAbort();取消当前线程的Abort

    如果线程已经Start、Abort,再次Start,则会抛出异常System.Threading.ThreadStateException。

    判断线程的状态:

    Console.WriteLine(t.ThreadState);       //判断的是线程的生命周期的状态;t.IsAlive是执行的状态

    线程优先级:

    Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);      //把所有的线程放在单个CPU上运行(便于测试看到效果)
    t.Priority = ThreadPriority.Lowest;     //可以get、set优先级

    多个线程操作同一个对象时——加锁:

    static void Main()
    {
        Console.WriteLine("Incorrect counter");     //先给出一个不加锁的,错误处理
        Counter c = new Counter();
        Thread t1, t2;
        t1 = new Thread(() => TestCounter(c));
        t2 = new Thread(() => TestCounter(c));
        t1.Start();
        t2.Start();
        t1.Join();
        t2.Join();
        Console.WriteLine("Total count: {0}", c.Count);
        Console.WriteLine("-------------------");
    
        Console.WriteLine("Correct counter");       //然后再加锁进行试验
        CounterWithLock c1 = new CounterWithLock();
        t1 = new Thread(() => TestCounter(c1));
        t2 = new Thread(() => TestCounter(c1));
        t1.Start();
        t2.Start();
        t1.Join();
        t2.Join();
        Console.WriteLine("Total count: {0}", c1.Count);
        t1.Abort();
        t2.Abort();
        //因为如果不加锁:假设当前对象的Count是10,那么可能线程1正在+1,得到11,还没有保存;与此同时线程2也在+1,也得到11。于是最后保存的结果就是11;但是按道理应该是12的 —— 错误原因
        //加了锁:lock另外一个对象,于是一个线程访问该对象时,其他线程是无法访问的,直到该线程访问完毕 —— 因此不会出现上面的情况
    }
    static void TestCounter(CounterBase c)
    {
        for(int i = 0; i < 100000; i++)
        {
            c.Decrement();
            c.Increment();
        }
    }

    以上做法,可能会造成死锁(例如有两把锁lock1、lock2:线程1先锁住了lock1,想要试图锁住lock2,却在此之前先Sleep较长时间,此时线程2趁机锁住lock2 —— 死锁产生:因为现在线程2是不能访问lock1的,如果线程2要访问lock1,则会等待线程1释放lock1;然而线程1在释放lock1之前,会先度过休眠期,然后访问lock2,但是也不行。故线程1、2都陷入不断等待的状态,即死锁状态(有一点还不明白,因为是线程,不像进程一样会分配大量资源,因此死锁也不会降低太多速度)。用代码解决死锁问题(先看下面的代码,再考虑这些问题):

    static void Main()
    {
        object lock1 = new object();
        object lock2 = new object();
    
        //为了避免死锁导致后面的程序无法执行,先使用可以断开deadLock的方式
        new Thread(() => LockTooMuch(lock1, lock2)).Start();
        lock (lock2)
        {
            Thread.Sleep(1000);
            //TryEnter的用法(TryEnter就是try{Enter})
            Console.WriteLine("Monitor.TryEnter allows not to get stuck, returning false after a specified timeout is elapsed");
            if(Monitor.TryEnter(lock1, TimeSpan.FromSeconds(5)))    //由于上面始终锁住lock1不放,故这里等多久都只能false
            {
                Console.WriteLine("Acquired a protected resource successfully");
            }
            else
            {
                Console.WriteLine("Timeout acquiring a resource!");
            }
        }
        //现在直接访问,肯定就deaLock啦
        new Thread(() => LockTooMuch(lock1, lock2)).Start();
        lock(lock2)
        {
            Thread.Sleep(1000);
            lock(lock1)
            {
                Console.WriteLine("Acquired a protected resource successfully");
            }
            Console.WriteLine("在前面已经锁住了,所以后面就不用写什么else了");
        }
    }
    static void LockTooMuch(object lock1, object lock2)
    {
        lock(lock1)
        {
            Thread.Sleep(1000);
            lock (lock2) ;
        }
    }
  • 相关阅读:
    Windows7与Window2008 64位IIS7上面DCOM配置Excel、Word
    C#连接SQLite的...方法
    VS2010版快捷键
    ajax 安装包下载
    Type InvokeMember()用法简介
    Lambda表达式
    多源最短路径算法
    单源点有权图的最短路径算法
    单源无权图的最短路径算法
    Tree Traversals Again
  • 原文地址:https://www.cnblogs.com/quanxi/p/6550559.html
Copyright © 2011-2022 走看看