Параллельный подход к вычислению простых чисел с использованием TParallel.For в Delphi
Вопрос разработчиков, работающих с параллельными вычислениями, часто связан с тем, как безопасно обращаться к общим ресурсам из разных потоков. Особенно актуальной эта задача становится при использовании коллекций, таких как TList, которые не являются потокобезопасными. В данном случае, рассматривается использование TParallel.For для вычисления простых чисел в диапазоне от 1 до 100000 и сохранения их в списке TList<Integer>.
Проблема
При использовании TParallel.For для параллельного вычисления простых чисел, возникает проблема с безопасным добавлением новых элементов в общий список TList<Integer>, так как он не предназначен для работы в многопоточной среде.
Решение
Для решения этой проблемы можно использовать механизмы синхронизации, такие как TCriticalSection или TMutex, которые позволяют защитить операции добавления элементов в список. Пример кода с использованием TCriticalSection:
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
AList: TList<Integer>;
ALock: TCriticalSection;
LoopResult: TParallel.TLoopResult;
begin
AList := TList<Integer>.Create;
ALock := TCriticalSection.Create;
try
TParallel.For(1, 100000, procedure(AIndex: Integer)
begin
if IsPrime(AIndex) then
begin
ALock.Enter;
try
AList.Add(AIndex);
finally
ALock.Leave;
end;
end;
end);
AList.Sort;
for i := 0 to AList.Count - 1 do
begin
Memo1.Lines.Add(IntToStr(AList[i]));
end;
finally
ALock.Free;
AList.Free;
end;
end;
Также можно использовать потокобезопасную коллекцию TThreadList<Integer>, которая автоматически обрабатывает синхронизацию:
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
AList: TThreadList<Integer>;
LList: TList<Integer>;
LoopResult: TParallel.TLoopResult;
begin
AList := TThreadList<Integer>.Create;
try
TParallel.For(1, 100000, procedure(AIndex: Integer)
begin
if IsPrime(AIndex) then
AList.Add(AIndex);
end);
LList := AList.LockList;
try
LList.Sort;
for i := 0 to LList.Count - 1 do
begin
Memo1.Lines.Add(IntToStr(LList[i]));
end;
finally
AList.UnlockList;
end;
finally
AList.Free;
end;
end;
Преимущества и недостатки
Использование TCriticalSection и TMutex требует внимательного обращения с ресурсами, чтобы избежать возможных блокировок и мертвых зависаний. Операции с этими механизмами синхронизации должны быть короткими и выполняться в блоке try-finally, чтобы гарантировать их освобождение в случае возникновения исключений.
TThreadList является более высокоуровневым и простым в использовании решением, так как он автоматически обрабатывает синхронизацию, но может быть менее эффективным в некоторых сценариях из-за дополнительных операций копирования списка.
Заключение
Параллельные вычисления с использованием TParallel.For в Delphi могут значительно ускорить обработку данных, но требуют особого внимания к вопросам потокобезопасности. Использование TCriticalSection, TMutex или TThreadList позволяет безопасно работать с общими ресурсами в многопоточной среде.
Описание контекста: Использование параллельных вычислений с TParallel.For в Delphi для нахождения простых чисел с обеспечением потокобезопасности при работе с общими ресурсами.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.