problem with multithreading in string sorting is not correct sorting

// создание потоков procedure TForm1.StartClick(Sender: TObject); var i: integer; begin chez := 0; chez2 := 0; c := -1; working := True; SetLength(thread_mass, Form1.SpinEdit.Value); for i := 0 to Form1.SpinEdit.Value -1 do begin thread_mass[i] := Potok.Create(True); thread_mass[i].Priority := tpNormal; thread_mass[i].FreeOnTerminate := True; thread_mass[i].Resume; end; end; // главный поток procedure Potok.Execute; begin while working do //работаем пока переменная равна тру begin try CS.Enter; //вход в критическую секцию Inc(c); // переменная глобальная накручивается чтоб посчитать количество потоков if c < Filez.Count then //условие условие сравнивает количество потоков и количество строк в глобальном объекте Filez potz := c // записываем данные с глобальной переменной в переменную которую я создал в классе самого потока else working := False; // если условие не выполнено то выходим из цикла finally // заставляем потоки покинуть секцию CS.Leave; // выход из критической секции end; if working then // проверяем цикл закончился или нет begin if pos('vasy',LowerCase(Filez.Strings[potz]))<> 0 then // проверка имени в строке begin rez := 1; Sleep(3); end else if pos('misha',LowerCase(Filez.Strings[potz]))<>0 then // проверка имени в строке begin rez := 1; Sleep(3); end else if pos('petia',LowerCase(Filez.Strings[potz]))<>0 then // проверка имени в строке begin rez := 1; Sleep(3); end else if pos('lexa',LowerCase(Filez.Strings[potz]))<>0 then // проверка имени в строке begin rez := 1; Sleep(3); end else // любые другие имена begin rez := 2; Sleep(3); end; Synchronize(Synhz); // синхонизируем данные end; end; end; //дальше синхронизация так как будем работать c vcl и ее глобальными переменными,объектами изменять их procedure Potok.Synhz; begin case rez of 1:begin inc(chez); // это счетчик глобальной переменной что вывести данные в лейбл rus_D.Add(Filez.Strings[potz]); // дабавление имен в глобальный объект с индексом переменной класса самого потока Form1.Label4.Caption := IntToStr(chez); // вывод самого счетчика end; 2:begin inc(chez2); //это другой счетчик глобальной переменной что вывести данные лейбл ether_D.Add(Filez.Strings[potz]); // дабавление имен в глобальный объект с индексом переменной класса самого потока Form1.Label12.Caption := IntToStr(chez2); // вывод самого счетчика end; end; end; 

actually, what is the mistake when sorting names and adding Russian names to the rus_D object, there are English ones that should fall into

object ether_D, as I understand it, it’s connected that I didn’t secure the streams, but I don’t see what error I’d be very grateful for the clarification of

what am i doing wrong and how to

Update

 var // глобально объявлена CS: TCriticalSection; // инициализируется при создании формы procedure TForm1.FormCreate(Sender: TObject); begin CS := TCriticalSection.Create; end; 

 type Potok = class(TThread) private { Private declarations } protected procedure Execute; override; procedure Synhz; public potz: Integer; //вот здесь объявлен { Public declarations } end; 
  • Filez list Filez after starting threads? - Anton Shchyrov
  • Critical section where declared and initialized? - Anton Shchyrov
  • Filez is not modified implementation <br> var <br> CS: TCriticalSection; <br> procedure TForm1.FormCreate (Sender: TObject); <br> begin <br> Filez: = TStringList.Create; <br> end; - Ivan
  • And where is the potz announced? - Anton Shchyrov

1 answer 1

Rez you have a global variable. And you write to this variable from different streams? A few milliseconds pass between recording and synchronization and a pair of rez and potz variables do not "point" to the same object.

In fact, I would do differently.

  1. You give a task to a specific stream instance (check from i to j).
  2. The stream checks and spreads the two global (non-visual) variables rus_D and ether_D. Writing to global variables in the critical section ( if objects are thread safe, then is it possible without a section ?). Changing global pointers, counters are also in the same critical section (here you can draw an analogy with transactions). Check and work with local variables outside the critical section, write to global variables in the critical one.
  3. Outside the stream (upon completion), we visualize rus_D and ether_D.

You need to carefully monitor the use of global variables. There is always the possibility that even such a simple operation like i: = i + 1 will be simultaneously launched in two threads and instead of answer 2 we get 1.

  • Well, you can also rez in an array to place, that is, for each thread its result. On the lines, by the way, I do not think that in general multithreading is justified. Even 1000 files in one stream will be processed faster than 10 files. - Albert Fomin