小编use*_*136的帖子

删除对象后,未完成的存储会发生什么?

考虑以下简单函数(假设大多数编译器优化关闭)由具有存储缓冲区的 X86 CPU 上不同内核上的两个线程执行:

struct ABC
{
  int x;
  //other members.
};
void dummy(int index)
{
  while(true)
  {
    auto abc = new ABC;
    abc->x = index;
    cout << abc->x;
    // do some other things.
    delete abc;
  }
}
Run Code Online (Sandbox Code Playgroud)

这里,index是线程的索引;1 由线程1 传递,2 由线程2 传递。因此,线程 1 应该始终打印 1,线程 2 应该始终打印 2。

是否存在这样的情况,即存储到x被放入存储缓冲区并在执行delete之后提交?或者是否存在隐式内存屏障来确保在删除之前提交存储?或者一旦遇到删除,任何未完成的存储都会被丢弃?

这变得很重要的情况:

由于delete是将对象的内存返回到空闲列表中(用libc),因此有可能在thread1中刚刚释放的一块内存被thread2中的new操作符返回(不仅是虚拟地址,甚至是返回的底层物理地址可以是相同的)。如果未完成的存储可以在删除后执行,则线程 2 将 abc->x 设置为 2 后,线程 1 中的某些较旧的未完成存储可能会将其覆盖为 1。

这意味着在上面的程序中,thread2可以打印1,这是绝对错误的。线程1和线程2是完全独立的,从程序员的角度来看,线程之间没有数据共享,并且它们不必担心任何同步。

我在这里缺少什么?

c++ x86 multithreading cpu-architecture memory-barriers

3
推荐指数
2
解决办法
197
查看次数