16,748
社区成员
发帖
与我相关
我的任务
分享
type
TPerson = class
end;
TMembers = TObjectList<TPerson>;
TGroup = class
private
fMembers: TMembers;
function GetMembers: TMembers;
public
destructor Destroy; override;
//...
property Members: TMembers read GetMembers;
end;
//...
destructor TGroup.Destroy;
begin
fMembers.Free;
inherited Destroy;
end;
function TGroup.GetMembers: TMembers;
begin
if fMembers = nil then
begin
fMembers := TMembers.Create;
end;
Result := fMembers;
end;
// fCriticalSection: SyncObjs.TCriticalSection;
constructor TGroup.Create;
begin
inherited Create;
fCriticalSection := TCriticalSection.Create;
end;
destructor TGroup.Destroy;
begin
fMembers.Free;
fCriticalSection.Free;
inherited Destroy;
end;
function TGroup.GetMembers: TMembers;
begin
fCriticalSection.Enter;
try
if fMembers = nil then
begin
fMembers := TMembers.Create;
end;
Result := fMembers;
finally
fCriticalSection.Leave;
end;
end;
function TGroup.GetMembers: TMembers;
begin
if fMembers = nil then // 先判断fMembers是否为nil,若为nil才进入临界区
begin
fCriticalSection.Enter;
try
if fMembers = nil then // 再次判断fMembers(这就是double-checked locking的由来)
begin
fMembers := TMembers.Create;
end;
finally
fCriticalSection.Leave;
end;
end;
Result := fMembers;
end;
function TGroup.GetMembers: TMembers;
begin
if fMembers = nil then
begin
fCriticalSection.Enter;
try
MemoryBarrier;
if fMembers = nil then
begin
fMembers := TMembers.Create;
end;
finally
fCriticalSection.Leave;
end;
end;
Result := fMembers;
end;
function TGroup.GetMembers: TMembers;
var
list: TMembers;
begin
if fMembers = nil then
begin
list := TMembers.Create;
if InterlockedCompareExchangePointer(fMembers, list, nil) <> nil then
begin
list.Free;
end;
end;
Result := fMembers;
end;
// fMembersSync: SysUtils.IReadWriteSync;
constructor TGroup.Create;
begin
inherited Create;
fMembersSync := TMREWSync.Create; // or TMultiReadExclusiveWriteSynchronizer.Create;
end;
destructor TGroup.Destroy;
begin
fMembers.Free;
inherited Destroy;
end;
function TGroup.FindMember(const name: string): TPerson;
var
person: TPerson;
begin
fMembersSync.BeginRead; // 查找成员是“读操作”
try
for person in Members do
begin
if SameText(person.Name, name) then
begin
Result := person;
Break;
end;
end;
finally
fMembersSync.EndRead;
end;
end;
procedure TGroup.AddMember(person: TPerson);
begin
fMembersSync.BeginWrite; // 添加成员属于“写操作”
try
Members.Add(person);
finally
fMembersSync.EndWrite;
end;
end;
// 这里用读写锁应该没有意义,是不是要用上面的某种方法来保证线程安全???
function TGroup.GetMembers: TMembers;
begin
end;
function TGroup.GetMembers: TMembers;
begin
if fMembers = nil then
begin
fCriticalSection.Enter;
try
MemoryBarrier;
if fMembers = nil then
begin
fMembers := TMembers.Create;
end;
finally
fCriticalSection.Leave;
end;
end;
Result := fMembers;
end;
上面是判断没有建立,就强制同步结程一致辞,如果还是判断没有,才建立?
"使用 MemoryBarrier 生成正确的多线程程序是非常困难的。在大多数情况下,C# 中的 lock 语句、Visual Basic 中的 SyncLock 语句和 Monitor 类的方法都提供了更简单的且不容易出错的方式来同步内存访问。建议您使用这些语句和方法,而不要使用 MemoryBarrier。"
这上面是MSDN上的一段话,搞得我有点犯迷糊了.
function TGroup.GetMembers: TMembers;
var
list: TMembers;
begin
if fMembers = nil then
begin
list := TMembers.Create;
if InterlockedCompareExchangePointer(fMembers, list, nil) <> nil then
begin
list.Free;
end;
end;
Result := fMembers;
end;
上面二种在高并发的情况下,上面的应该好过下面这个吧?