С филосовской точки зрения всё равно потоки не стартуют одновременно, так как процессор-то один.
Но с точки зрения программирования можно предложить следующее решение с потоками-стартерами рабочих потоков.
class Program
{
static List<Thread> threads = new List<Thread>(); // Список потоков
static int threadCount = 10; // Число потоков
static ManualResetEvent startEvent = new ManualResetEvent(false); // Событие для старта рабочих потоков
static volatile int starterCount = 0; // Счётчик запущенных потоков. volatile показывает, что переменная будет изменяться в различных потоках и её не надо оптимизировать
static object LockObject = new object(); // Блокировка для изменения переменной starterCount
static void Main(string[] args)
{
// Создаём пул потоков
for (int i = 0; i < threadCount; i++)
{
Thread thread = new Thread(Work);
threads.Add(thread);
}
// На старт — запускаем стартовые потоки и ждём их запуска
foreach (var thread in threads)
new Thread(Starting).Start(thread);
while (starterCount < threadCount) Thread.Sleep(1);
// Внимание — к этому моменту все стартовые потоки запустились и ожидают на WaitOne()
Thread.Sleep(100);
// Марш — установка события отпускает приостановленные потоки
startEvent.Set();
while (true) ;
}
static void Starting(object paramThread)
{
lock (LockObject)
{
starterCount++;
}
startEvent.WaitOne();
(paramThread as Thread).Start();
}
static void Work()
{
return;
}
}