1

这是一个简单的 C# 示例程序的稍微修改版本:

using System;
using System.Threading;

namespace SemaphorTest
{
    class Program
    {
        static Semaphore gate = new Semaphore(3, 3);
        static void Main(string[] args)
        {
            for (int i = 0; i < 5; i++)
            {
                Thread t = new Thread(Enter);
                t.Start(i);
            }
        }

        public static void Enter(Object id)
        {
            Console.WriteLine("Thread " + id + " wants to enter.");
            gate.WaitOne();
            Console.WriteLine("Thread " + id + " is in.");
            Thread.Sleep(500 * (Int32)id);
            Console.WriteLine("Thread " + id + " leaving.");
            gate.Release();
        }
    }
}

这将打印以下输出(似乎是随机顺序):

Thread 0 wants to enter.
Thread 1 wants to enter.
Thread 1 is in.
Thread 0 is in.
Thread 2 wants to enter.
Thread 3 wants to enter.
Thread 0 leaving.
Thread 3 is in.
Thread 4 wants to enter.
Thread 2 is in.
Thread 1 leaving.
Thread 4 is in.
Thread 2 leaving.
Thread 3 leaving.
Thread 4 leaving.

但是,如下添加 Thread.Join() 会极大地改变输出。即:

for (int i = 0; i < 5; i++)
            {
                Thread t = new Thread(Enter);
                t.Start(i);
                t.Join();
            }

将输出更改为:

Thread 0 wants to enter.
Thread 0 is in.
Thread 0 leaving.
Thread 1 wants to enter.
Thread 1 is in.
Thread 1 leaving.
Thread 2 wants to enter.
Thread 2 is in.
Thread 2 leaving.
Thread 3 wants to enter.
Thread 3 is in.
Thread 3 leaving.
Thread 4 wants to enter.
Thread 4 is in.
Thread 4 leaving.

为什么会这样?我知道这些线程默认是前台线程,并且主线程不需要等待它们完成(即使在 Main 完成后它们也会运行,因此它们在这里不需要 thread.Join())。但我不明白是什么让它们按照更改后创建的顺序运行。有任何想法吗 ?

Thanks
Dileep Balakrishnan 
4

3 回答 3

8

为什么会这样?

因为你要求它!

您已经启动了一个线程,然后等待它完成,然后启动下一个线程等等。这正是Thread.Join它所做的:它阻塞当前正在执行的线程,直到您调用它的线程终止。

我感兴趣的是您期望该代码执行的操作...如果您只想等到所有线程完成后再让主线程完成,则需要启动所有线程,并在执行过程中记住它们,然后依次调用Join每个。例如:

List<Thread> threads = new List<Thread>();
// First start all the threads
for (int i = 0; i < 5; i++)
{
    Thread t = new Thread(Enter);
    t.Start(i);
    threads.Add(t);
}

// Then wait for them to finish
foreach (var thread in threads)
{
    thread.Join();
}
于 2013-04-08T16:07:35.373 回答
1

您正在将每个线程与调用线程连接起来。这实际上将阻塞调用线程并等待每个线程依次结束。

文档中它指出:

阻塞调用线程,直到线程终止。

于 2013-04-08T16:07:24.260 回答
0

Thread.join() 不会让事情同时运行。它实际上通过阻塞当前线程直到它完成来强制执行您所看到的行为。这在文档中明确提到:http: //msdn.microsoft.com/en-us/library/95hbf2ta.aspx

于 2013-04-08T16:08:19.573 回答