是否会立即生成所有工作线程?

时间:2017-05-16 05:06:20

标签: c# multithreading thread-safety

是否有人可以向我解释此代码的流程? 我想知道主线程如何生成工作线程,我知道的是:

一旦主线程调用.start方法,它就会创建一个新线程。 但是,当我在main中循环多个线程时,行为会发生变化,这让我很困惑。

static void Main()
{
Thread[] tr = new Thread[10];
for (int i = 0; i < 10; i++)
{

    tr[i] = new Thread(new ThreadStart(count));
    tr[i].Start();

}

static private void count()
{

    for (int i = 0; i < 10; ++i)
    {
        lock (theLock)
        {
            Console.WriteLine("Count {0} Thread{1}",
            counter++, Thread.CurrentThread.GetHashCode());

        }
    }

是否有一种调试和跟踪多线程程序的好方法。谷歌之后,我发现在调试情绪中跟踪线程窗口,但即使给线程提供自定义名称后,我也发现它无用。 我只是无法理解流程,如何启动线程,它们如何一起工作等等,因为断点在多线程应用程序中似乎没有效果。 (至少在我的情况下。)

2 个答案:

答案 0 :(得分:0)

  

我希望这个输出1由Thread打印:4551 [ThreadID] 2打印   线程:4552 3由线程打印:4553 4由线程打印:4554 5   线程印刷:4555 6线程印刷:4556 7印刷   线程:4557 8由线程打印:4558 9由线程打印:4559 10   线程:4560 11由线程打印:4551 [相同的线程ID   再次出现,如1] 12由Thread打印:4552

我将尝试描述您的代码在与线程子系统交互时所做的工作。我给出的细节来自我在OS设计大学课程中记得的内容,因此主机操作系统和/或CLR内部的实际实现可能与我所描述的有所不同。

static void Main()
{
Thread[] tr = new Thread[10];
for (int i = 0; i < 10; i++)
{

    tr[i] = new Thread(new ThreadStart(count));

    // The following line puts the thread in a "runnable" thread list that is
    // managed by the OS scheduler. The scheduler will allow threads to run by 
    // considering many factors, such as how many processes are running on 
    // the system, how much time a runnable thread has been waiting, the process
    // priority, the thread's priority, etc.  This means you have little control 
    // on the order of execution, The only certain fact is that your thread will
    // run, at some point in the near future.
    tr[i].Start();  

    // At this point you are exiting your main function, so the program should
    // end, however, since you didn't flag your threads as BackgroundThreads,
    // the program will keep running until every thread finishes.
}


static private void count()
{
   // The following loop is very short, and it is probable that the thread
   // might finish before the scheduler allows another thread to run
   // Like user2864740 suggested, increasing the amount of iterations will 
   // increase the chance that you experience interleaved execution between
   // multiple threads

    for (int i = 0; i < 10; ++i)
    {
        // Acquire a mutually-exclusive lock on theLock. Assuming that
        // theLock has been declared static, then only a single thread will be
        // allowed to execute the code guarded by the lock.    
        // Any running thread that tries to acquire the lock that is
        // being held by a different thread will BLOCK. In this case, the 
        // blocking operation will do the following:
        //    1. Register the thread that is about to be blocked in the
        //       lock's wait list (this is managed by a specialized class
        //       known as the Monitor)
        //    2. Remove the thread that is about to be blocked from the scheduler's
        //       runnable list. This way the scheduler won't try to yield
        //       the CPU to a thread that is waiting for a lock to be
        //       released.  This saves CPU cycles.
        //    3. Yield execution (allow other threads to run)
        lock (theLock)
        {
            // Only a single thread can run the following code
            Console.WriteLine("Count {0} Thread{1}",
            counter++, Thread.CurrentThread.GetHashCode());

        }
        // At this point the lock is released.  The Monitor class will inspect
        // the released lock's wait list. If any threads were waiting for the
        // lock, one of them will be selected and returned to the scheduler's
        // runnable list, where eventually it will be given the chance to run
        // and contend for the lock. Again, many factors may be evaluated 
        // when selecting which blocked thread to return to the runnable  
        // list, so we can't make any guarantees on the order the threads
        // are unblocked
    }
}

希望事情更清楚。 这里重要的是承认您几乎无法控制各个线程的执行计划,因此无法(没有相当数量的同步代码)复制您期望的输出。最多,您可以更改线程的优先级,以提示调度程序某个线程必须优先于其他线程。但是,这需要非常小心地完成,因为它可能会导致一个被称为优先级倒置的令人讨厌的问题。除非你确切知道自己在做什么,否则通常最好不要改变线程的优先级。

答案 1 :(得分:0)

经过不断的尝试,我完成了我的任务要求。这是代码:

using System;
using System.Threading;
public class EntryPoint
{
    static private int counter = 0;
    static private object theLock = new Object();
    static object obj = new object();
    static private void count()
    {
        {
                for (int i = 0; i < 10; i++)
            {
                lock (theLock)
                {
                    Console.WriteLine("Count {0} Thread{1}",
                    counter++, Thread.CurrentThread.GetHashCode());
                     if (counter>=10) 
                    Monitor.Pulse(theLock);
                    Monitor.Wait(theLock);  }  }}
    }
    static void Main()
    {
        Thread[] tr = new Thread[10];
        for (int i = 0; i < 10; i++)
        {
            tr[i] = new Thread(new ThreadStart(count));
            tr[i].Start();
        }

    }
} 

Monitor按顺序维护一个就绪队列,因此我实现了我想要的目标:

Here is the output

干杯!