c# - 线程优先级(如何获得固定顺序)

标签 c# multithreading

在控制台中,因为线程随机 sleep ,它将显示线程的顺序
3,2,1或1,2,3或...
我怎样才能有固定的订单?
为什么设置优先级不会影响代码?
//ThreadTester.cs
//以不同的时间间隔打印多线程。

    using System;
    using System.Threading;

    namespace threadTester
    {
        // class ThreadTester demonstrates basic threading concepts
        class ThreadTester
        {
            static void Main(string[] args)
            {
                // Create and name each thread. Use MessagePrinter's
                // Print method as argument to ThreadStart delegate.
                MessagePrinter printer1 = new MessagePrinter();
                Thread thread1 =
                   new Thread(new ThreadStart(printer1.Print));
                thread1.Name = "thread1";

                MessagePrinter printer2 = new MessagePrinter();
                Thread thread2 =
                   new Thread(new ThreadStart(printer2.Print));
                thread2.Name = "thread2";

                MessagePrinter printer3 = new MessagePrinter();
                Thread thread3 =
                   new Thread(new ThreadStart(printer3.Print));
                thread3.Name = "thread3";

                Console.WriteLine("Starting threads");

                // call each thread's Start method to place each 
                // thread in Started state
                thread1.Priority = ThreadPriority.Lowest;
                thread2.Priority = ThreadPriority.Normal;
                thread3.Priority = ThreadPriority.Highest;
                thread1.Start();
                thread2.Start();
                thread3.Start();

                Console.WriteLine("Threads started\n");
                Console.ReadLine();

            } // end method Main

        } // end class ThreadTester

        // Print method of this class used to control threads
        class MessagePrinter
        {
            private int sleepTime;
            private static Random random = new Random();

            // constructor to initialize a MessagePrinter object
            public MessagePrinter()
            {
                // pick random sleep time between 0 and 5 seconds
                sleepTime = random.Next(5001);
            }

            // method Print controls thread that prints messages
            public void Print()
            {
                // obtain reference to currently executing thread
                Thread current = Thread.CurrentThread;

                // put thread to sleep for sleepTime amount of time
                Console.WriteLine(
                   current.Name + " going to sleep for " + sleepTime);

                Thread.Sleep(sleepTime);

                // print thread name
                Console.WriteLine(current.Name + " done sleeping");

            } // end method Print

        } // end class MessagePrinter
    }

最佳答案

您之所以使用线程正是因为您不关心事情按特定顺序发生,而是想要:

  • 同时,如果有足够的核心允许它们一起发生。
  • 有些人在进步,而另一些人在等待某些东西。
  • 交错处理,注意I/O或用户输入,以便继续响应。

  • 在每种情况下,您都不必关心自己什么时候会发生什么。

    然而:
  • 您可能仍然会关心某些序列的顺序。在最简单的情况下,只需让这些事情在同一线程中依次发生,而其他事情在其他线程中发生。通过将任务链接在一起,可以处理更复杂的情况。
  • 您可能希望最终将来自不同线程的结果放入不同的顺序中。最简单的方法是在它们全部完成之后将它们全部排序,尽管您也可以在它们来时对结果进行排序(虽然有点棘手)。

  • 为了获得理想的性能,每个时刻都应该在每个内核上运行一个线程(或者在超线程内核上可能运行两个线程,但这会带来更多的复杂性)。假设您有一台具有4个核心和8个任务的计算机。

    如果任务涉及大量等待I/O的任务,那么将启动四个任务,每个任务都将达到等待该I/O的地步,并允许其他任务之一取得一些进展。很有可能即使任务数是内核数的两倍,它最终仍将有大量空闲时间。如果每个任务要花费20秒,那么在不同的线程上执行它们可能会使它们都在20秒多一点的时间内完成,因为所有这些都花了20秒的大部分时间在等待其他事情。

    如果您正在执行使CPU一直忙碌的任务(没有太多等待内存,当然也没有I/O),那么您一次可以执行四个这样的任务,而其他任务正在等待它们要么结束,要么放弃自己的时间。在这里,如果每一个都花费20秒,那么您最好的总时间就是大约40秒(并且假设系统上任何进程的其他线程都不需要CPU,那么您在设置CPU时就完全没有开销了)线程等)。

    如果有更多的工作要做( Activity 工作要做,而不是等待I/O完成,另一个线程释放锁,等等),而不是内核,则OS调度程序将在不同线程之间进行交换。积极点。确切的细节因操作系统而异(不同的Windows版本,包括台式机和服务器设置之间的一些重要差异,采用不同的方法,不同的Linux版本以及从2.4到2.6的特别大的更改以及不同的Unix等)都具有不同的策略)。

    他们共有的一件事是确保完成任务的共同目标。

    线程优先级和进程优先级是影响此调度的方式。使用Windows,每当有更多线程在等待工作而不是核心在工作时,那些优先级最高的线程将以循环方式获得给定的CPU时间。如果没有该优先级的线程,那么将给倒数第二个线程分配CPU时间,然后分配下一个,依此类推。

    这是使事情停滞不前的好方法。当一个被赋予高优先级的线程(大概是因为它的工作被认为是至关重要的)正在等待一个被赋予低优先级的线程(可能是因为它的工作被认为不那么重要,并且人们希望它总是将时间浪费在线程上)时,这可能会导致复杂化。其他优先级),并且低优先级线程不会一直被分配CPU时间,因为总是有比可用内核更高优先级的线程。因此,所谓的高优先级线程根本没有CPU时间。

    为了解决这种情况,Windows有时会提升长时间未运行的线程。这可以解决问题,但是现在意味着您已经拥有了所谓的低优先级线程,并且以超高优先级爆发,不仅损害了应用程序的其余部分,而且损害了系统的其余部分。

    (拥有多核系统的最好的事情之一是,这意味着您的计算体验受设置线程优先级的人员的影响较小!)

    如果使用调试器停止多线程.NET应用程序并检查线程,您可能会发现除了最高的线程以外,所有其他线程均正常。最高级别的终结器线程是终结器线程,并且它的最高优先级运行是终结器不要花很长时间执行的重要性的原因之一-以最高优先级完成工作是一件坏事,尽管这样做是有道理的在这种情况下,必须尽快结束。

    在所有其他情况下,至少有95%的情况是有人设置了线程的优先级,这是一个逻辑错误-大部分时间它什么都不做,其余的事情会变得一团糟。它们可以很好地使用(或者根本不具备这种能力),但是绝对应该将它们放在“高级技术”类别中。 (我喜欢把自己的空闲时间花在尝试多线程技术上,这些技术在大多数时候通常被认为是过度和过早的优化,而且我仍然很少碰到优先事项)。

    在您的示例中,优先级的影响很小,因为每个线程都将大部分时间都花在 sleep 上,因此,任何想要CPU时间的线程都可以在需要运行的纳秒时间内获得它。但是,如果您在内核也忙于其他普通线程的机器上运行它,那么整个事情就会变得不必要地变慢。在这种情况下,thead1最初不会获得任何CPU时间(因为总是有更高优先级的线程需要CPU),然后在3秒钟后,调度程序将意识到它永远饿死了CPU速度(90亿个CPU周期或90亿个CPU周期)。因此),并使其具有最高优先级的爆发时间足够长,以使其与重要的Windows服务的时间保持一致!幸运的是,它随后进入休眠状态,然后完成一分钟的工作,然后再完成操作,因此它没有害处,但是,如果它做的是真正的事情,则可能会对整个系统的性能产生某些令人讨厌的影响。

    关于c# - 线程优先级(如何获得固定顺序),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8683079/

    相关文章:

    c# - 我将如何使用字典解析此 JSON?

    c# - 为什么这个 F# 代码这么慢?

    java - 当你调用一个线程的 interrupt() 时会发生什么?

    multithreading - 在Windows中使用事件同步线程

    c# asp.net core Bearer错误="invalid_token"

    c# - Linq 从另一个区间列表中选择任何区间内的所有数字

    c# - 创建集合中所有元素的深拷贝的通用方法

    objective-c - 在Objective-C中使用指针式分配与 setter 方法有多危险?

    multithreading - 线程加工 AX 2012

    java - Java 中的同步多线程(Apache HTTPClient)