【问题标题】:C#, thread priorities, and locksC#、线程优先级和锁
【发布时间】:2013-09-30 14:01:09
【问题描述】:

在 C# 中,如果一个高优先级任务已准备好执行,并且另一个(低优先级)线程已经在监视器中,那么低优先级任务是否会在以下两种情况下被抢占:

  1. 较高优先级的任务想要获取一个(或多个)由低优先级任务获取的锁。
  2. 高优先级任务不需要低优先级任务获取的任何锁。

编译器/操作系统是否在任务抢占方面做了任何聪明的事情,还是总是高优先级的任务总是抢占低优先级的任务?

【问题讨论】:

    标签: c# multithreading locking preemption


    【解决方案1】:

    对于问题的第一个场景感兴趣的朋友,下面是我做的一个实验,用来测试处理锁时的线程抢占:

    object resourselock = new object();
    
        public void Test()
        {
            Thread lowestThread = new Thread(new ThreadStart(Low));
            lowestThread.Priority = ThreadPriority.Lowest;
    
            Thread highestThread = new Thread(new ThreadStart(High));
            highestThread.Priority = ThreadPriority.Highest;
    
            lowestThread.Start();
            Thread.Sleep(1000);   //makes sure that the lowest priority thread starts first
            highestThread.Start();
        }
    
        
        public void Low()
        {
            Console.WriteLine("Low priority task executed");
    
            lock (resourselock)
            {
                Console.WriteLine("Low priority task will never release the lock!");
    
                while (true) ; //infinite empty statement!
            }
        }
    
        public void High()
        {
            System.Console.WriteLine("High priority task executed");
    
            lock (resourselock)
            {
                System.Console.WriteLine("High priority task got the lock!"); //this will never be reached!
            }
        }
    

    以下是程序的输出:

    执行的低优先级任务

    低优先级任务永远不会释放锁!

    执行的高优先级任务

    虽然高优先级任务需要获得resourcelock(低优先级任务已经获得)才能执行,但执行高优先级任务只是发现它不能执行!!因此,当任务需要资源来执行时,编译器没有进行任何优化来防止不必要的上下文切换。

    【讨论】:

      【解决方案2】:

      如果更高优先级的线程正在等待锁,无论哪个线程拥有锁,都不会被调度。

      如果较高优先级的线程没有等待任何东西,那么它可能会抢占较低优先级的线程。不过,这些都不是真正的 .NET 或 C# 特定的 - 它实际上最终取决于操作系统来管理线程并安排它们。

      您可能会发现this MSDN article on thread priorities 很有用 - 它在某些方面确实让我感到惊讶。特别是:

      系统以循环方式将时间片分配给具有最高优先级的所有线程。如果这些线程都没有准备好运行,则系统以循环方式将时间片分配给具有下一个最高优先级的所有线程。如果较高优先级的线程可以运行,系统将停止执行较低优先级的线程(不允许其完成使用其时间片),并将完整的时间片分配给较高优先级的线程。

      应该能够通过创建一些高优先级线程和一些低优先级线程的程序来验证这一点;上面的引用表明,如果您可以让处理器忙于高优先级线程,那么低优先级线程将完全饿死。这让我感到惊讶,但你应该能够进行实验,看看会发生什么。试着让高优先级线程忙于不能导致任何 IO(等)的工作,否则会导致它们停止。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-09
        相关资源
        最近更新 更多