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) ;
        }
    }
  • 相关阅读:
    UVALive 7141 BombX
    CodeForces 722D Generating Sets
    CodeForces 722C Destroying Array
    CodeForces 721D Maxim and Array
    CodeForces 721C Journey
    CodeForces 415D Mashmokh and ACM
    CodeForces 718C Sasha and Array
    CodeForces 635C XOR Equation
    CodeForces 631D Messenger
    田忌赛马问题
  • 原文地址:https://www.cnblogs.com/quanxi/p/6550559.html
Copyright © 2011-2022 走看看