我有一个TParallel。& For循环。在这个循环中,我创建并使用TMyClass对象来进行计算。结果存储在ResultList中。
type
TMyCommonClass=class(TList<Real>)
private
function DoCalculation(const AValue: Integer): Real;
end;
type
TMyClass=class(TList<Real>)
private
MyCommonClass: TMyCommonClass;
function DoCalculation(const AValue: Integer): Real;
end;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
MyCommonClass: TMyCommonClass;
end;
function TMyCommonClass.DoCalculation(const AValue: Integer): Real;
var
r: Real; //some local vars
begin
r:=Items[AValue]*100; //some example calculations using local vars
Result:=r;
end;
function TMyClass.DoCalculation(const AValue: Integer): Real;
begin
Result:=MyCommonClass.DoCalculation(AValue);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
MyCommonClass:=TMyCommonClass.Create;
for i := 0 to 1000000 do //add some example data to the list
begin
MyCommonClass.Add(i*0.01);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ALock: TCriticalSection;
LoopResult: Tparallel.TLoopResult;
ResultList: TList<Real>;
i: Integer;
begin
ResultList:=TList<Real>.Create;
try
ALock:=TCriticalSection.Create;
try
LoopResult:=TParallel.&For(0, 100000,
procedure(AIndex: Integer)
var
MyClass: TMyClass;
r: Real;
begin
MyClass:=TMyClass.Create;
MyClass.MyCommonClass:=MyCommonClass;
try
r:=MyClass.DoCalculation(AIndex);
begin
ALock.Enter;
try
ResultList.Add(r);
finally
ALock.Leave;
end;
end;
finally
MyClass.Free;
end;
end);
finally
ALock.Free;
end;
ResultList.Sort;
//show the result list
for i := 0 to ResultList.Count-1 do
begin
Memo1.Lines.Add(FloatToStr(ResultList[i]));
end;
finally
ResultList.Free;
end;
end;
我的示例代码有效。但我不确定它是否正确并且始终有效。
方法MyClass.DoCalculation调用在程序启动时创建的TMyCommonClass对象的DoCalculation方法。
为每个循环创建和销毁TMyClass。但是,TMyCommonClass对象只存在一次,因此不同的线程将并行访问它。
据我所知,我不能在不考虑同步的情况下写入TMyCommonClass,但我不确定是否读取数据和使用方法。
问题是:
从TMyCommonClass对象读取数据是否可以?
TMyCommonClass是TList的后代。使用Items [i]?
可以像我在TMyCommonClass.DoCalculation的示例中一样调用TMyCommonClass的方法吗?这里局部变量和方法参数会发生什么?是否保证每个线程都为局部变量和方法参数获取自己的内存空间,以便它是线程安全的?
答案 0 :(得分:2)
从
TMyCommonClass
对象读取数据是否可以?
阅读始终是线程安全的。当您写入common
课程时会出现问题。如果你做了任何写操作,你需要确保其他线程在写入之前写入或之前获取数据。
危险在于其他线程在写入中途获得数据(即损坏的数据)
您需要使用锁定,关键部分,原子写入或其他一些机制来防范这种情况。
TMyCommonClass是TList的后代。使用Items [i]?
读取数据是否可以
正如我上面所述,阅读没问题,但如果你写信TCommon
,你需要采取措施。 TList
没有内置的线程安全措施,你需要使用像TThreadList
这样的线程安全列表(它使用锁定)。如果您有更高级的需求,请参阅:How can I implement a thread-safe list wrapper in Delphi?
可以像我在TMyCommonClass.DoCalculation的示例中那样调用TMyCommonClass的方法吗?这里局部变量和方法参数会发生什么?是否保证每个线程都为局部变量和方法参数获取自己的内存空间,以便它是线程安全的?
是的,DoCalculation
没问题,前提是您始终可以信任{TMyCommonClass.}Items[AValue]
返回有效数据。
局部变量存在于堆栈中,每个线程都有自己的堆栈,保证永远不会与其他堆栈发生冲突
方法参数通过寄存器和堆栈传递,因此这些也是安全的。