1
14
这是我第二次尝试回答。我只回答你的第一个问题:
不,因为你是在说你自己,你只是在确保对象创建受到保护,而不是对象引用的初始化。 在没有C++ 98内存模型和没有来自编译器供应商的显式语句的情况下,不能保证将表示实际引用的内存写入到包含引用标志初始化值的内存(如果是它是如何实现的),则以相同的顺序从多个THE中看到。广告。 正如您所说,用相同的值多次重写引用应该不会产生语义差异(即使存在单词撕裂,这在您的处理器体系结构中通常是不可能的,甚至是不可能的),但有一种情况很重要: 当多个线程在程序执行期间第一次争用调用函数时 . 在这种情况下,一个或多个线程可以在初始化实际引用之前看到正在设置的初始化标志。 你的程序中有一个潜在的bug,你需要修复它。至于优化,除了使用双重检查的锁定模式之外,我确信还有很多。 |
2
5
这是我的看法(如果在启动线程之前确实无法初始化它): 我已经看到(并使用)类似的东西来保护静态初始化,使用boost::once
在我的理解中,所有线程都会以这种方式等待boost::call_一次,但创建静态变量的线程除外。它将只创建一次,然后再也不会被调用。然后你就没有锁了。 |
3
3
因此,本规范的相关部分为6.7/4:
假设第二部分成立(
通过3.6.2,似乎允许的早期初始化正在转换 动态初始化 到 静态初始化 . 自从 静态初始化 必须发生在任何之前 动态初始化 既然我想不出任何方法来创建线程,直到你 动态初始化 ,这样的早期初始化也将保证构造函数被调用一次。 更新
所以,在呼叫
这就留下了关于覆盖引用的问题,这个引用肯定没有被规范所覆盖。也就是说,如果您愿意假设引用是通过指针实现的(我认为这是最常见的实现方法),那么您要做的就是用它已经拥有的值覆盖一个指针。所以我认为这在实践中应该是安全的。 |
4
0
我不是标准化的… 但是对于您提到的用途,为什么不在创建任何线程之前简单地初始化它们呢?许多单例问题都是由于人们使用惯用的“单线程”延迟初始化,而在加载库时,他们可以简单地实例化值(就像典型的全局变量)。 只有当您使用另一个“全局”的值时,懒惰的时尚才有意义。 另一方面,我看到的另一种方法是使用某种协调:
尽管我可能没有准确地描述它。 |
5
0
总之,我认为:
[我假设C++引用是使用指针值来实现对实际对象的引用,这在理论上可以在部分写入到“读取”时被读取。 所以,试着回答你的问题:
更新: 在发布这个答案之后,我意识到它只关注实际问题的一个小的、深奥的部分,因此决定发布另一个答案而不是编辑内容。我将保留“原样”的内容,因为它与这个问题有一定的关联(同时也是为了谦虚自己,提醒我在回答之前多思考一些事情)。 |
6
0
我已经编程了足够多的进程间套接字来做噩梦。为了在具有DDR RAM的CPU上保证任何线程安全,您必须缓存行对齐数据结构,并将所有的全局变量连续打包到尽可能少的缓存行中。 未对齐的进程间数据和松散打包的全局数据的问题是,它会导致缓存未命中产生别名。在使用DDR RAM的CPU中,通常有一组64字节的缓存线。当您加载一条缓存线时,DDR RAM将自动加载更多的缓存线,但第一条缓存线总是最热的。高速中断发生的情况是,缓存页将像模拟信号一样充当低通滤波器,并过滤掉导致 完全地 如果你不知道到底发生了什么事情,你会发现令人困惑的虫子。同样的事情也适用于未紧密打包的全局变量;如果它占用多个缓存线,它将失去同步,除非您获取关键进程间变量的快照并在堆栈和寄存器上传递它们,以确保数据正确同步。 .bss部分(即存储全局变量的位置)将被初始化为所有零,但编译器不会为您缓存行对齐数据,您必须自己执行该操作,这也可能是使用 C++ Construct in Place . 要学习后面的数学最快的方法对齐指针,请阅读 this article 我想知道我是否想出了那个把戏。下面是代码的外观:
根据我的经验,你必须使用指针,而不是参考。 |
7
-1
只需在开始创建线程之前调用函数,从而保证引用和对象。或者,不要使用如此糟糕的设计模式。我的意思是,为什么在地球上对一个静止物体有一个静止的参照物?为什么还要有静态物体?这没什么好处。单身是个糟糕的主意。 |
8
-1
这似乎是我所能想到的最简单/最干净的方法,而不需要所有的互斥香奈儿:
|
a a · 为什么在这个可重入锁示例中需要引用计数? 2 年前 |
Grant · goroutines有高空闲唤醒电话 2 年前 |
hoaz · 如何安全地清理并发映射 6 年前 |
Alanpatchi · int基元类型的volatile声明 6 年前 |