3

我正在构建一个模拟赛马的小型应用程序,以获得一些使用线程的基本技能。

我的代码包含这个循环:

        for (int i = 0; i < numberOfHorses; i++)
        {
            horsesThreads[i] = new Thread(horsesTypes[i].Race);
            horsesThreads[i].Start(100);
        }

为了保持比赛的“公平”,我一直在寻找一种方法,让所有新创建的线程等到设置了其余的新线程,然后才启动所有线程以开始运行它们的方法(请注意我知道从技术上讲,线程不能在“同时”启动)

所以基本上,我正在寻找这样的东西:

        for (int i = 0; i < numberOfHorses; i++)
        {
            horsesThreads[i] = new Thread(horsesTypes[i].Race);
        }
        Monitor.LaunchThreads(horsesThreads);
4

3 回答 3

3

线程不保证公平或确定性结果,因此它不是模拟比赛的好方法。

话虽如此,有些同步对象可能会满足您的要求。我认为屏障类(Fx 4+)是你想要的。

于 2013-08-08T07:48:37.700 回答
1

我会把 aManualResetEvent作为一扇门;里面Thread递减一个计数器;如果仍然非零,则在门口等待;否则,打开大门。基本上:

using System;    
using System.Threading;
class Program
{
    static void Main()
    {
        ManualResetEvent gate = new ManualResetEvent(false);
        int numberOfThreads = 10, pending = numberOfThreads;
        Thread[] threads = new Thread[numberOfThreads];
        ParameterizedThreadStart work = name =>
        {
            Console.WriteLine("{0} approaches the tape", name);
            if (Interlocked.Decrement(ref pending) == 0)
            {
                Console.WriteLine("And they're off!");
                gate.Set();
            }
            else gate.WaitOne();
            Race();
            Console.WriteLine("{0} crosses the line", name);
        };
        for (int i = 0; i < numberOfThreads; i++)
        {
            threads[i] = new Thread(work);
            threads[i].Start(i);
        }
        for (int i = 0; i < numberOfThreads; i++)
        {
            threads[i].Join();
        }
        Console.WriteLine("all done");

    }
    static readonly Random rand = new Random();
    static void Race()
    {
        int time;
        lock (rand)
        {
            time = rand.Next(500,1000);
        }
        Thread.Sleep(time);
    }

}
于 2013-08-08T08:05:37.803 回答
1

该类Barrier旨在支持这一点。

这是一个例子:

using System;
using System.Threading;

namespace Demo
{
    class Program
    {
        private void run()
        {
            int numberOfHorses = 12;

            // Use a barrier with a participant count that is one more than the
            // the number of threads. The extra one is for the main thread,
            // which is used to signal the start of the race.

            using (Barrier barrier = new Barrier(numberOfHorses + 1))
            {
                var horsesThreads = new Thread[numberOfHorses];

                for (int i = 0; i < numberOfHorses; i++)
                {
                    int horseNumber = i;
                    horsesThreads[i] = new Thread(() => runRace(horseNumber, barrier));
                    horsesThreads[i].Start();
                }

                Console.WriteLine("Press <RETURN> to start the race!");
                Console.ReadLine();

                // Signals the start of the race. None of the threads that called
                // SignalAndWait() will return from the call until *all* the 
                // participants have signalled the barrier.

                barrier.SignalAndWait();

                Console.WriteLine("Race started!");
                Console.ReadLine();
            }
        }

        private static void runRace(int horseNumber, Barrier barrier)
        {
            Console.WriteLine("Horse " + horseNumber + " is waiting to start.");
            barrier.SignalAndWait();
            Console.WriteLine("Horse " + horseNumber + " has started.");
        }

        private static void Main()
        {
            new Program().run();
        }
    }
}

[编辑] 我刚刚注意到 Henk 已经提到过Barrier,但我会在这里留下这个答案,因为它有一些示例代码。

于 2013-08-08T08:23:08.253 回答