Объясните порядок выполнения потока здесь?

#c# #multithreading

#c# #многопоточность

Вопрос:

Из приведенного ниже кода я подумал, что «y» будет напечатано перед x, но «x» начнет печататься первым. Я читаю это линейным способом, так почему же «x» начинает печатать первым, хотя t.Start() вызывается первым в основном методе?

 static void Main()
{

    Thread t = new Thread(ThreadTest.WriteY);
    t.Start();

    for(int i = 0; i < 1000; i  ) Console.Write("x");
}

public class ThreadTest
{
    public static void WriteY()
    {
    for(int i = 0; i < 1000; i  ) Console.WriteLine("y");
    }
}
  

Комментарии:

1. Потому что в ту же секунду, когда вы начинаете использовать несколько потоков, вы теряете детерминизм.

2. Не могли бы вы объяснить немного подробнее?

3. Проще говоря, нет гарантии, что система выполнит ваши потоки в определенном порядке. Запуск нового потока не обязательно приведет к завершению текущего потока, например.

4. Похоже, вы действительно хотите спросить: «что такое поток?»

Ответ №1:

Что ж, рассмотрим это таким образом.

Дайте вашему другу стопку документов и оставьте стопку себе.

Затем вы говорите своему другу «начни выписывать цифры на этих бумагах», а затем сразу же начинаете делать то же самое.

Теперь скажите мне, кто из вас закончит первым?

И, учитывая, что это ваш вопрос, почему?

Здесь невозможно детерминированно ввести правильный ответ, потому что существует так много факторов, влияющих на то, насколько быстро вы двое можете:

  • начните записывать числа
  • запишите числа
  • переходите к следующему листу бумаги

Таким образом, в принципе, ваш друг может начать раньше, чем вам удастся запустить, или наоборот, но вы не можете знать заранее, и это не «правильный ответ».

Каждый раз, когда вы запускаете эту программу, у нее есть шанс вести себя по-разному, по крайней мере, с точки зрения порядка выполнения между двумя потоками.

С учетом сказанного, при запуске нового потока возникают накладные расходы, которые могут склонить чашу весов в пользу основного потока, входящего в цикл раньше, чем это сделает дополнительный поток. Однако я был бы удивлен, если не существует способа, которым могло бы произойти обратное.

Комментарии:

1. Ну, я бы закончил первым :). Серьезно, хорошая аналогия. Спасибо

2. Поскольку это вопрос C # (технически это вопрос .NET, но все же), я предполагаю, что правильный термин здесь Stack<Paper> , нет? 🙂

Ответ №2:

Когда вы запускаете новый поток, операционная система берет управление на себя и планирует выполнение работы на более позднее время. Дело в том, что у вас нет способа узнать, когда это произойдет, поэтому вы запускаете одно и то же приложение несколько раз и каждый раз видите разные результаты.

Ответ №3:

Запуск нового потока может потребовать довольно много времени, поэтому WriteY запуск займет некоторое время. Тем временем основной поток будет продолжать выполняться, и, таким образом, вы увидите много x напечатанных s в большинстве, если не во всех случаях.

Кроме того, само планирование обрабатывается операционной системой.

Короче говоря: Вы не должны пытаться угадать порядок выполнения на основе чтения исходного кода.

Ответ №4:

Просто потому, что вы запускаете поток в определенное время, не означает, что код в этом потоке запустится до выполнения следующей строки кода в вызывающем методе.

Я бы предположил, что вы могли запускать программу тысячи раз и в итоге некоторые из них начинались на «y», а другие — на «x».

Комментарии:

1. Да, это именно то, что происходит.

Ответ №5:

порядок выполнения потока непредсказуем

в этом случае, вероятно, это будет код, который создает поток (stackframe / etc), Который замедляет работу

Ответ №6:

Потому что не гарантировано, что запускается первым. Не существует детерминированного порядка, в котором выполняются потоки. Если вы запускаете свою программу n раз, можно предположить, что вы видите, что сначала печатаются x и y.

Если вы хотите обеспечить порядок в способах выполнения потоков, вам следует посмотреть на Thread.Присоединиться

Комментарии:

1. Есть ли способ установить порядок, например, выполнить основной поток, а затем выполнить другой поток?