我希望这个输出 1 由 Thread 打印:4551 [ThreadID] 2 由 Thread 打印
线程:4552 3 由线程打印:4553 4 由线程打印:4554 5
线程打印:4555 6 线程打印:4556 7 打印
线程:4557 8 由线程打印:4558 9 由线程打印:4559 10
由线程打印:4560 11 由线程打印:4551 [相同线程 ID
再次出现,如 1] 12 由 Thread 打印:4552
我将尝试描述您的代码在与线程子系统交互时所做的事情。我提供的细节来自我在大学操作系统设计课程中的记忆,因此主机操作系统和/或 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
}
}
希望事情更清楚。 这里重要的是要承认,您几乎无法控制各个线程如何安排执行,因此无法(没有大量同步代码)复制您期望的输出。 ,您可以更改线程的优先级以提示调度程序某个线程必须优先于其他线程。然而,这需要非常小心地完成,因为它可能会导致一个被称为优先级反转的令人讨厌的问题。除非您确切知道自己在做什么,否则通常最好不要更改线程的优先级。