首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >混合原子运算与非原子运算

混合原子运算与非原子运算
EN

Stack Overflow用户
提问于 2019-01-09 07:12:48
回答 1查看 189关注 0票数 5

在delphi源代码中,我们有:

代码语言:javascript
复制
class function TNetEncoding.GetBase64Encoding: TNetEncoding;
var
  LEncoding: TBase64Encoding;
begin
  if FBase64Encoding = nil then
  begin
    LEncoding := TBase64Encoding.Create;
    if AtomicCmpExchange(Pointer(FBase64Encoding), Pointer(LEncoding), nil) <> nil then
      LEncoding.Free
{$IFDEF AUTOREFCOUNT}
    else
      FBase64Encoding.__ObjAddRef
{$ENDIF AUTOREFCOUNT};
  end;
  Result := FBase64Encoding;
end;

但我不明白,它们混合了原子操作 (AtomicCmpExchange(Pointer(FBase64Encoding), Pointer(LEncoding), nil)非原子操作,如if FBase64Encoding = nil thenResult := FBase64Encoding; )

这不是个错误吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-09 08:39:56

在注释中,您清楚地表明,您所关心的是不受保护的内存操作可能会被撕毁。撕裂是指读取线程在部分写入变量时读取它。

这在一般情况下是合理的,但在这种情况下不可能发生撕裂。其原因是,对齐内存访问保证不会被撕破。当内存操作对齐时,读取器无法读取部分写入的变量。这通常是通过硬件总线序列化单个缓存行中的所有内存访问来保证的。

所以,不,这不是一个错误,代码是正确的。

代码本身习惯于懒洋洋地创建单例程序。采用线程安全方式这样做的一种常见技术是双重检查锁定。此代码使用一种避免锁定的替代技术。相反,代码可能允许多个线程推测地创建单例。如果多个线程成功地创建了对象,那么成功的第一个线程将获胜,而其他线程将销毁它们的实例并使用winner线程创建的实例。

如果创建附加实例然后销毁它们是良性的,则无锁方法工作得很好。但情况并非总是如此。例如,创建实例的多个副本可能过于昂贵。在这种情况下,基于锁的方法更好。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54104882

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档