2015-08-20 3 views
4

Я пытаюсь понять преимущества параллельной библиотеки задач, используя традиционную многопоточность, и когда я думаю о ситуации ниже, я застрял, думая, что она обрабатывает состояние гонки или делает это нужно обрабатывать это в нашем коде?Является ли задача о параллельной библиотеке задач (TPL)

Вот мой код:

int depdt = 0;  
Parallel.For(1, 10, mem => 
     { 

      for (int dep = 1; dep <= 10; dep++) 
      { 
       depdt = dep; 
       Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep); 
      } 

      Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem); 
     }); 
     Console.ReadKey(); 

Я побежал его пару раз, и я не вижу какой-либо поток мешая/перезапись на «depdt» переменной. Но мне нужно это подтвердить. (Или) Для того, чтобы сделать его поточно я должен вручную создать экземпляр класса и реализовать его как код ниже, чтобы избежать условий гонки

int depdt = 0; 
     Parallel.For(1, 10, mem => 
     { 
       Worker worker = new Worker(); 
       worker.DoWork(mem); 

     }); 
     Console.ReadKey(); 

    public class Worker 
{ 
    public void DoWork(int mem) 
    { 

     int depdt = 0; 
     for (int dep = 1; dep <= 10; dep++) 
     { 
      depdt = dep; 
      Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep); 
     } 

     Console.WriteLine("Dep Value: " + depdt +" "+ "mem: "+ mem); 
    } 
} 

ответ на @yms: Я имею в виду при использовании нормальных потоков выполнения depdt становится Название переменной ненадежный. Вот мой код:

for (int mem = 1; mem <= 10; mem++) 
     { 
      var t= new Thread(state => 
      { 
       for (int dep = 1; dep <= 10; dep++) 
       { 
        depdt = dep; 
        Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep); 
       } 

       Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem); 
      }); 

      t.Start(string.Format("Thread{0}", mem)); 
     } 
     Console.ReadKey(); 

Вот мой вывод на экран: Infact как MEM и DEP переменные становятся ненадежными

enter image description here

+0

Обратите внимание, что переменная присвоения 4 байта Int [обычно атомарных] (http://stackoverflow.com/questions/8290768/is-assignment-operator-atomic). Также я не вижу необходимости вводить новый класс, вы могли бы просто использовать локальную переменную в выражении лямбда – yms

+0

@yms. Я имею в виду, используя обычную Threading, вы обычно попадаете в такое состояние, где переменная «depdt» становится ненадежной. См. Мой ниже код и его результат с Threads – marak

+0

@yms Я добавил дополнительную информацию в вопрос, отвечая на ваш комментарий. Спасибо – marak

ответ

3

Если вы ожидаете, что ваша программа всегда будет писать Dep Value: 10, то да, ваша программа подвержена условию гонки, которое может привести к печати других значений. Чтобы продемонстрировать эту проблему, просто ввести задержку во внутреннем цикле:

int depdt = 0; 
Parallel.For(1, 10, mem => 
{ 
    for (int dep = 1; dep <= 10; dep++) 
    { 
     depdt = dep; 
     Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep); 
     Thread.Sleep(mem * 100); // delay introduced here 
    } 
    Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem); 
}); 
Console.ReadKey(); 

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

Чтобы избежать состояния гонки, вам просто нужно, чтобы переместить depdt декларацию внутри анонимную функцию передается Parallel.For. Это приведет к тому, что каждый поток будет иметь свою собственную переменную, избегая конфликтов.

Parallel.For(1, 10, mem => 
{ 
    int depdt = 0; 
    for (int dep = 1; dep <= 10; dep++) 
    { 
     depdt = dep; 
     Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep); 
    } 
    Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem); 
}); 
+0

Спасибо Дуглас. Итак, суть TPL не имеет встроенного механизма для обработки состояния гонки, его нужно обрабатывать в нашем коде. – marak

+1

@marak: [Общий параллелизм памяти] (https://en.wikipedia.org/wiki/Parallel_programming_model#Shared_memory) по своей природе восприимчив к условиям гонки. Поскольку вы указали свою переменную как общую для всех потоков, тогда было возможно ожидать, что для нескольких потоков будет доступ к ней одновременно. Это на самом деле иногда желательно поведение, как в случае флагов сторожевого знака для завершения фоновых операций. – Douglas

1

№ Задача параллельная библиотека не обрабатывает условия гонки по умолчанию. Вам необходимо позаботиться о синхронизации доступа к общим ресурсам.

Смежные вопросы