Meyers 的单例实现实际上是如何实现单例的

2024-04-29

我读了很多关于单例的内容,什么时候应该使用它们,什么时候不应该使用它们,以及如何安全地实现它们。我正在用 C++11 编写,并且遇到了 Meyer 的单例延迟初始化实现,如所示这个问题。 https://stackoverflow.com/questions/1661529/is-meyers-implementation-of-singleton-pattern-thread-safe

这个实现是:

static Singleton& instance()
{
     static Singleton s;
     return s;
}

我明白这对于其他问题来说是如何线程安全的,但我不明白的是这实际上是一个单例模式。我已经用其他语言实现了单例,这些结果总是像这个例子一样维基百科 http://en.wikipedia.org/wiki/Singleton_pattern:

public class SingletonDemo {
        private static volatile SingletonDemo instance = null;

        private SingletonDemo() {       }

        public static SingletonDemo getInstance() {
                if (instance == null) {
                        synchronized (SingletonDemo .class){
                                if (instance == null) {
                                        instance = new SingletonDemo ();
                                }
                      }
                }
                return instance;
        }
}

当我查看第二个示例时,很直观地看出这是一个单例,因为该类持有对其自身一个实例的引用,并且只返回该实例。但是,在第一个示例中,我不明白这如何防止该对象存在两个实例。所以我的问题是:

  1. 第一个实现如何强制执行单例模式?我认为它与 static 关键字有关,但我希望有人可以向我深入解释幕后发生的事情。
  2. 在这两种实现方式之间,哪一种更可取?优缺点都有什么?

谢谢你的帮助,


这是一个单例,因为static本地函数的存储持续时间意味着程序中仅存在该本地函数的一个实例。

在底层,这可以非常粗略地被认为等同于以下 C++98(甚至可能由编译器像这样模糊地实现):

static bool __guard = false;
static char __storage[sizeof(Singleton)]; // also align it

Singleton& Instance() {
  if (!__guard ) {
    __guard = true;
    new (__storage) Singleton();
  }
  return *reinterpret_cast<Singleton*>(__storage);
}

// called automatically when the process exits
void __destruct() {
  if (__guard)
    reinterpret_cast<Singleton*>(__storage)->~Singleton();
}

线程安全位使它变得有点复杂,但本质上是一样的。

看看 C++11 的实际实现,有一个保护变量对于每个静态(如上面的布尔值),它也用于屏障和线程。查看 Clang 的 AMD64 输出:

Singleton& instance() {
   static Singleton instance;
   return instance;
}

AMD64 程序集instance来自 AMD64 上的 Ubuntu 的 Clang 3.0,位于 -O1(由http://gcc.godbolt.org/ http://gcc.godbolt.org/ is:

instance():                           # @instance()
  pushq %rbp
  movq  %rsp, %rbp
  movb  guard variable for instance()::instance(%rip), %al
  testb %al, %al
  jne   .LBB0_3
  movl  guard variable for instance()::instance, %edi
  callq __cxa_guard_acquire
  testl %eax, %eax
  je    .LBB0_3
  movl  instance()::instance, %edi
  callq Singleton::Singleton()
  movl  guard variable for instance()::instance, %edi
  callq __cxa_guard_release
.LBB0_3:
  movl  instance()::instance, %eax
  popq  %rbp
  ret

可以看到它引用了一个全局守卫来查看是否需要初始化,使用__cxa_guard_acquire,再次测试初始化​​,依此类推。几乎在所有方面都与您从维基百科发布的版本完全相同,除了使用 AMD64 程序集和中指定的符号/布局安腾ABI http://refspecs.linux-foundation.org/cxxabi-1.83.html#guards.

请注意,如果您运行该测试,您应该给出Singleton一个不平凡的构造函数,因此它不是一个 POD,否则优化器将意识到没有必要执行所有这些保护/锁定工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Meyers 的单例实现实际上是如何实现单例的 的相关文章

  • WebClient.DownloadDataAsync 冻结了我的 UI

    我在 Form 构造函数中的 InitializeComponent 之后有以下代码 using WebClient client new WebClient client DownloadDataCompleted new Downloa
  • 元组在 VS2012 中如何工作?

    Visual Studio 2012 功能 tuples但不是可变参数模板 这是如何完成的 如何在不使用可变模板的情况下实现元组 简而言之 微软做了与之前在 NET 中实现类似元组的数据类型完全相同的事情 创建许多版本 每个版本都有固定数量
  • 是否可以从 C++ 应用程序调用 C# 应用程序?

    我是一名编程学生 现在我已经上了两门 C 课程 这个学期我将参加我的第一门 C 课程 出于好奇 是否可以从 C 应用程序调用 C 应用程序 如果是的话 是否还可以检查运行该程序的计算机是否具有 NET框架 我只是很好奇 我想如果可能的话 这
  • c# 从另一个类中的另一个静态事件引发事件

    需要帮助从另一个班级调用事件 我有已声明事件的课程 public class MxPBaseGridView GridView public event AddNewItemsToPopUpMenuEventHandler AddNewIt
  • 司机和提供商之间的区别

    数据库中的驱动程序和提供程序有什么区别 有没有解释一下 不胜感激 样本 ADO NET driver for MySQL vs providerName System Data EntityClient 来自 MSDN 论坛 驱动程序是安装
  • 进度状态报告模式

    我正在实现需要显示进程栏 或进度百分比 的长时间运行的进程 长时间运行的过程的整体逻辑很复杂 各种分页数据检索 因此 我最终在代码中的不同位置硬编码了大量百分比 在更新完成百分比时 什么被认为是最佳设计模式 我发现 JFace 周围使用的模
  • 在 ASP.NET MVC 中将模型从视图传递到控制器

    我正在 ASP NET MVC 中开发我的第一个应用程序 但遇到了一个我无法解决的问题 即使在阅读了整个互联网之后也是如此 因此 我有几个使用视图模型创建的视图 它们是报告 这些视图模型是根据用户选择标准填充的 我正在尝试构建一种接受模型并
  • while循环中的变量初始化

    我有一个可以分块读取文件的函数 public static DataObject ReadNextFile 数据对象看起来像这样 public DataObject public string Category get set And ot
  • 如何使用 Roslyn 通过扩展方法、静态类中的方法以及带有 ref/out 参数的方法来访问调用

    我正在致力于创建一个开源项目 用于创建 NET UML 序列图 该项目利用名为 js sequence diagrams 的 javascript 库 我不确定 Roslyn 是适合这项工作的工具 但我想我应该尝试一下 所以我整理了一些概念
  • 你好,我最近正在开发我的新游戏,我遇到了*无限跳跃*的问题

    所以基本上当我按跳跃 空格键时我会跳跃但是如果我连续按空格键它 只是跳啊跳啊跳等等 我不想要我只想它跳一次 code if Input GetKeyDown space isGrounded velocity y Mathf Sqrt ju
  • 通过 C# Mailkit / Mimekit 发送电子邮件,但出现服务器证书错误

    Visual Studio 2015 中的 0 代码 1 我正在使用 Mailkit 最新版本 1 18 1 1 从我自己的电子邮件服务器发送电子邮件 2 电子邮件服务器具有不受信任的自签名证书 3 我在代码中添加了以下两行 以忽略服务器证
  • Xamarin - SignalR 挂在连接上

    我正在尝试将我的 Xamarin 应用程序连接到托管在 Azure 上的 SignalR 后端 我遇到的问题是每次我在 HubConnection 上调用 StartAsync 时 它都会挂起客户端并且请求永远不会完成 我尝试通过应用程序进
  • 无法为 wsdl 文件创建服务引用

    I have wsdl文件和xsd我本地机器上的文件 我想在项目中添加服务引用 我没有网络服务 我只有wsdl file 我收到以下错误 The document was understood but it could not be pro
  • 使用 OleDbCommandBuilder 时访问 SQL 语法错误

    我要在 C 中使用 OleDbDataAdapter 在 Access 数据库中插入数据 但收到错误消息INSERT INTO 命令中的语法错误 BackgroundWorker worker new BackgroundWorker Ol
  • 使用 xslt 将 xml 转换为 xsl-fo 时动态创建超链接?

    我想使用 xsl 文件在 PDF 报告中创建标题 如果源文件包含超链接 则应将其呈现为超链接 否则呈现为纯文本 例如 我的 xml 如下所示 a href http google com target blank This is the h
  • 浮点字节序?

    我正在为实时海上模拟器编写客户端和服务器 并且由于我必须通过套接字发送大量数据 因此我使用二进制数据来最大化可以发送的数据量 我已经了解整数字节顺序以及如何使用htonl and ntohl为了规避字节顺序问题 但我的应用程序与几乎所有模拟
  • 在哪里可以下载没有 Visual Studio 2010 的 C# 4.0 编译器?

    我知道 CTP VS 2010 映像 但我可以只下载 NET Framework 4 0 和 C 编译器吗 AFAIK VS 2010 CTP 仅作为 VM 映像提供 我不相信 Microsoft 发布了 VS 的安装程序 其中一个绝对不适
  • 有没有办法直接在函数参数中格式化字符串而不是使用临时字符串?

    我有一个接受字符串 字符数组 作为参数的函数 void enterString char my string 当使用这个函数时 我经常发现自己想要输入格式化的字符串 我使用 sprintf 来做到这一点 然而 我每次都必须创建一个临时字符串
  • 如何将 int 作为“void *”传递给线程启动函数?

    我最初有一个用于斐波那契变量数组的全局变量 但发现这是不允许的 我需要进行基本的多线程处理并处理竞争条件 但我无法在 pthread 创建中将 int 作为 void 参数提供 我尝试过使用常量指针 但没有成功 由于某些奇怪的原因 void
  • C++ Boost ASIO 简单的周期性定时器?

    我想要一个非常简单的周期性计时器每 50 毫秒调用我的代码 我可以创建一个始终休眠 50 毫秒的线程 但这很痛苦 我可以开始研究用于制作计时器的 Linux API 但它不可移植 I d like使用升压 我只是不确定这是否可能 boost

随机推荐

  • 将表单重置为原始状态(AngularJS 1.0.x)

    AngularJS 1 1 x 的路线图上有一个将表单字段重置为原始状态 重置脏状态 的功能 不幸的是 当前的稳定版本中缺少这样的功能 对于 AngularJS 1 0 x 将所有表单字段重置为其初始原始状态的最佳方法是什么 我想知道这是否
  • div 上的背景图像未显示; div 正在折叠

    CSS body background url ninabg jpg left top no repeat background size 100 auto image background repeat no repeat backgro
  • 带有工具栏和 TabLayout 的 ViewPager 高度错误

    我在 AppBarLayout 下方有一个 ViewPager 带有工具栏和 TabLayout 我无法理解为什么加载的片段的高度大于可用空间 即使没有如此大的元素 使选项卡可滚动 这是主要的布局 xml
  • 如何仅在一个分支的提交上“git bisect”?

    在我目前正在进行的一个项目中 我们将每个功能保留为自己的分支 并在功能准备就绪时将其合并回主分支 每个功能分支内的提交可能包括大量 WIP 并破坏其他功能的功能 直到它完整且稳定 无论如何 由于主分支的提交是唯一 据说 稳定的提交 我想gi
  • 仅当其他对象成功创建时才创建对象

    我对 Django 相当陌生 并且不熟悉这种情况的最佳实践 在任何框架 语言中 而不仅仅是 python django 情况是 当用户第一次在我的网站上注册时 我想为他们创建一个 组织 如果它不存在 然后随后为他们创建一个引用该组织的用户
  • Swift(UI) 错误:无法在不可变值上使用变异成员:“self”是不可变的

    基本上我想做的是 如果您按下按钮 那么条目应该获得一个新的 CEntry 如果有人能帮助我那就太好了 谢谢 struct AView View var entries CEntries var body some View ZStack V
  • 将自定义操作添加到 UserModel 的管理页面

    是否有可能在 django UserModel 的管理页面中创建自定义操作 我希望自动将用户添加到组中 例如将他添加到员工中 设置一些额外的值等 当然还要创建收回这些更改的操作 感谢您的帮助 Import User在你的 admin py
  • 如何发送/接收 JSON?

    我知道这是一个愚蠢的问题 但我通常不进行 Web 编程 并且被要求发送一些 JSON 数据并接收一些回报 我用谷歌搜索 很清楚如何编码和解码 JSON 数据 但我对此很陌生 我不知道如何与给定的 URL 进行通信并说 这里有一些数据 请发回
  • 如何修复 Visual Studio 2015 Preview 上 SDL 2.0.3 未解析的外部问题?

    所以我收到以下错误 1 gt SDL2main lib SDL windows main obj error LNK2019 unresolved external symbol imp fprintf referenced in func
  • JMockit + Jetty 进行功能测试

    我在集成测试中使用 ShrinkWrap 启动 Jetty 服务器 Problem 示例项目中的 JUnit 测试试图模拟ForwardingServlet班级 但是 在这种具有嵌入式 Jetty Web 服务器的场景中 实际上有two该类
  • 获取 UIView 的当前角度/旋转/弧度?

    如何获取 UIView 当前的角度 旋转 弧度 你可以这样做 CGFloat radians atan2f yourView transform b yourView transform a CGFloat degrees radians
  • 使用 Maven 和 cxf-codegen-plugin 将 WSDL 客户端打包在 JAR 中

    我有一个 Maven 项目 它将使用许多 Web 服务 该应用程序将打包为 WAR 到目前为止 客户的代码已经生成cxf codegen plugin 在里面generate sources阶段 默认情况下 生成的源放入target gen
  • 使用 CDK 创建 ssh 密钥对/将其关联到 ec2 实例

    我正在使用新的云开发工具包 CDK 使用 Java 语言在 AWS 上构建基础设施 我在公共子网上使用堡垒主机与私有子网上的 RDS 实例进行通信 因此我通过堡垒主机上的 ssh 隧道从外部访问数据库 在私有子网上 我以这种方式创建了 Ba
  • 在 JavaScript 中实现撤消功能 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 如何在 javascript 中实现 ctrl z 经过多次谷歌搜索后 我偶然发现了 execCommand 我在用着document
  • 如何让 MediaRouteSelector 显示可用的 MiraCast 和 Chromecast 设备?

    我正在尝试让我的媒体路由选择器同时显示 MiraCast 和 Chromecast 设备 我有一个 Chromecast 接收器应用程序 并且还使用 Android 中的演示 API 因此理想情况下 用户只需单击媒体路由器按钮并选择他们拥有
  • bash:PWD 和 CURDIR 有什么区别?

    我的问题 我使用 Makefile 来运行docker runtarget 需要当前工作目录作为其参数之一 我使用任一 PWD or CURDIR build Dockerfile docker run lt PWD or CURDIR g
  • 如何在 .NET 4+ 中实现 ISerialized 而不违反继承安全规则?

    背景 野田时间 https nodatime org包含许多 可序列化的结构 虽然我不喜欢二进制序列化 但我们 早在 1 x 时间线中就收到了许多支持它的请求 我们通过实施ISerializable界面 我们最近收到了一份问题 报告 htt
  • 如何从一个端口为 Jetty 提供 https 和 http 服务?

    我知道这是一个重复的问题 但原始发帖者提出这个问题的原因是错误的 我并不是暗示我问它是为了right原因 但让我们看看 我们有一个在非标准端口号上运行的 Web 服务 尽管用户似乎能够记住端口号 但有时他们会错误地输入 http 而不是 h
  • C# 和 .NET 的“最佳”数据访问框架/方法是什么?

    编辑 我将其设为社区维基 因为它更适合协作格式 有多种方法可以从 NET 访问 SQL Server 和其他数据库 一切都有其优点和缺点 这永远不会是一个简单的问题 哪个是 最好的 答案永远是 这取决于 然而 我正在寻找在不同级别的系统背景
  • Meyers 的单例实现实际上是如何实现单例的

    我读了很多关于单例的内容 什么时候应该使用它们 什么时候不应该使用它们 以及如何安全地实现它们 我正在用 C 11 编写 并且遇到了 Meyer 的单例延迟初始化实现 如所示这个问题 https stackoverflow com ques