是否有人可以向我解释此代码的流程? 我想知道主线程如何生成工作线程,我知道的是:
一旦主线程调用.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());
}
}
是否有一种调试和跟踪多线程程序的好方法。谷歌之后,我发现在调试情绪中跟踪线程窗口,但即使给线程提供自定义名称后,我也发现它无用。 我只是无法理解流程,如何启动线程,它们如何一起工作等等,因为断点在多线程应用程序中似乎没有效果。 (至少在我的情况下。)
答案 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按顺序维护一个就绪队列,因此我实现了我想要的目标:
干杯!