【发布时间】:2020-01-15 02:44:00
【问题描述】:
我有一个如下形状的类
TParser = class
private
FFlag : boolean;
FIntermediateValue : double;
procedure F1(var aPartOfInput : string);
procedure F2(var aSmallerPartOfInput : string) ;
public
function Parse(const anInput : string): double;
end;
function TParser.Parse(const anInput : string) : double;
var
aPartOfInput : string;
begin
{ Do some checks on the input and set FFlag to true/false.
Set aPartOfInput to a piece of the input}
f1(aPartOfInput);
Result := FIntermediateValue;
end;
procedure TParser.F1(var aPartOfInput : string);
begin
{ Slice some more off the input.
Set the FIntermediateValue }
f2(aPartOfInput)
end;
procedure TParser.F2(var aSmallerPartOfInput : string);
begin
{ Depending on the input and FFlag, update FIntermediateValue }
end;
我们目前通过系统创建/销毁其中的一个 squillion(技术术语)。
我正在考虑创建一个实例并从每个位置调用它。
这个单一实例将从多个线程中调用。
使用私有字段是否意味着这不是线程安全的?
如果这不是线程安全的,我有哪些选项可以使它成为线程安全的?
编辑 - 选项
感谢所有cmets。
每个线程都有一个单独的实例
听起来不错,但由于代码的结构方式,实例需要对线程是“全局的”,没有办法(据我所知)将实例注入对象图到需要的地方(目前,在需要的地方创建解析器的新实例)
threadvar
TheParser : TParser;
似乎是给我这个的一种方式。当我们启动线程时创建实例并在离开时释放它。这有什么问题吗?
摆脱实例变量
如果我们重新设计解析器,让它成为一个函数而不是一个类的实例,并且所有的值都被传递,这会让它成为线程安全的吗?
interface
function Parse(const anInput : string): double;
implementation
function F2(var aSmallerPartOfInput : string; theFlag : boolean; theIntermediateValue : double) : double ;
begin
{ update theIntermediateValue based on flag and input }
Result := theIntermediateValue;
end;
function F1(var aPartOfInput : string; theFlag : boolean) : double;
var
anIntermediateValue : double;
begin
{ Slice some more off the input
Set the FIntermediateValue }
Result := f2(aPartOfInput, theFlag, anIntermediateValue)
end;
function Parse(const anInput : string) : double;
var
aPartOfInput : string;
aFlag : boolean;
begin
{ set aFlag
set aPartOfInput to a piece of the input }
Result := f1(aPartOfInput, aFlag);
end;
【问题讨论】:
-
定义线程安全?上面代码中的上下文太少,但是如果有不同的线程访问私有字段(读取和写入),即使它们是通过对象实例执行此操作,那么此代码不是线程安全的。 What is thread safety anyway?
-
一切都将调用公共
Parse()函数,在幕后没有任何工作。我担心说,在线程 1 上我们调用Parse()并且 FFlag 设置为 true,然后在线程 2 上我们调用Parse()并且 FFlag 设置为 false,然后返回线程 1F2()使用 false 值。我不知道这是否有可能 -
需要序列化访问
Parse。 -
...或为每个线程创建一个单独的解析器实例...
-
使某些东西成为线程安全的最简单方法是为每个执行线程设置不同的实例。单个全局实例基本上是线程安全的敌人。
标签: multithreading delphi