zoukankan      html  css  js  c++  java
  • 《C#高级编程》读书笔记(十五):任务、线程和同步之三 Thread类

        Thread类允许创建前台线程,以及设置线程的优先级。使用Thread类可以创建和控制线程。

        在默认情况下,用Thread类创建的线程是前台线程线程池中的线程总是后台线程

            static void Main(string[] args)
            {
                var t1 = new Thread(ThreadMain);
                t1.Start();
                Console.WriteLine("This is the main thread.");
                Console.ReadKey();
            }
    
            static void ThreadMain()
            {
                Console.WriteLine("Running in a thread.");
            }

        不能保证哪个结果先输出。线程有操作系统调度,每次哪个线程在前面可以不同。

        也可以用Lambda表达式:

            static void Main(string[] args)
            {
                var t1 = new Thread(()=>Console.WriteLine(
                    $"running in a thread,id: {Thread.CurrentThread.ManagedThreadId}"));
                t1.Start();
                Console.WriteLine($"This is the main thread,id:{Thread.CurrentThread.ManagedThreadId}");
                Console.ReadKey();
            }

    1,后台线程

        在用Thread类创建线程时,可以设置IsBackground属性,以确定该线程是前台线程还是后台线程。

    var t1 = new Thread(ThreadMain)
               { Name = "MyNewThread",IsBackground = false};

    2,线程的优先级

        线程有操作系统调度。由线程指定优先级,就可以影响调度顺序。

        在Thread类中,可以设置Priority属性,以影响线程的基本优先级。

    3,争用条件

        如果两个或多个线程访问相同的对象,并且对共享状态的访问没有同步,就会出现争用条件。

        用一个例子来说明争用条件:

    public class StateObject
        {
            private int state = 5;
    
            public void ChangeState(int loop)
            {
                if (state == 5)
                {
                    state++;
                    Trace.Assert(state == 6,"Race condition occurred after"+loop+"loops");
                }
                state = 5;
            }
        }
    public class SampleTask
        {
            public void RaceCondition(object o)
            {
                Trace.Assert(o is object,"o must be of type StateObject");
                StateObject state = o as StateObject;
    
                int i = 0;
                while (true)
                {
                    state.ChangeState(i++);
                }
            }
        }
    static void Main(string[] args)
            {
              var state = new StateObject();
                for (int i = 0; i < 2; i++)
                {
                    Task.Run(() => new SampleTask().RaceCondition(state));
                }
               Console.ReadKey();
            }

        要避免该问题,可以用lock语句锁定在线程中共享的state变量。

        只有引用类型才能用于锁定,因为值类型没有SyncBlock字段,lock本质上Monitor.Enter,Monitor.Enter会使值类型装箱,每次lock的是装箱后的对象。

    4,死锁

         过多的锁定也会有麻烦。在死锁中,至少有两个线程被挂起,并等待对方解除锁定。由于两个线程都在等在对方,就出现了死锁,线程将无限等待下去。

    public class SampleTask
        {
            private StateObject s1, s2;
            public SampleTask(StateObject s1, StateObject s2)
            {
                this.s1 = s1;
                this.s2 = s2;
            }
    
            public void Deadlock1()
            {
                int i = 0;
                while (true)
                {
                    lock (s1)
                    {
                        lock (s2)
                        {
                            s1.ChangeState(i);
                            s2.ChangeState(i++);
                            Console.WriteLine($"still running,{i}");
                        }
                    }
                }
            }
    
            public void Deadlock2()
            {
                int i = 0;
                while (true)
                {
                    lock (s2)
                    {
                        lock (s1)
                        {
                            s1.ChangeState(i);
                            s2.ChangeState(i++);
                            Console.WriteLine($"still running,{i}");
                        }
                    }
                }
            }
    
        }
                var state1 = new StateObject();
                var state2 = new StateObject();
                new Task(new SampleTask(state1,state2).Deadlock1).Start();
                new Task(new SampleTask(state1, state2).Deadlock2).Start();

        F5运行,然后点击“全部中断”,再打开调试->窗口->任务,就可以看到,线程出于死锁状态。

  • 相关阅读:
    Google Map JavaScript API V3 实例大全
    C# 求斐波那契数列的前10个数字 :1 1 2 3 5 8 13 21 34 55
    软件开发模型
    powerdesigner 使用的几点问题
    JavaScript生成GUID的多种算法小结
    Asp.net 定时写入文本记录
    WebClient.UploadValues Post中文乱码的解决方法
    2014年总结与2015年目标
    单元测试
    前台页面Josn 数组在后台.cs代码中的解析
  • 原文地址:https://www.cnblogs.com/khjian/p/5801059.html
Copyright © 2011-2022 走看看