繁体   English   中英

C ++线程之间的内存共享

[英]Memory sharing between C++ threads

我是C ++新线程的新手,我试图清楚地了解线程之间如何共享/不共享内存。 我正在使用std::thread和C ++ 11。 从我在其他SO问题上看到的, 堆栈内存只由一个线程拥有, 内存在线程之间共享。 所以从我认为我对堆栈与堆的理解,以下内容应该是正确的:

#include <thread>
using namespace std;

class Obj {
public:
    int x;
    Obj(){x = 0;}
};

int main() {
    Obj stackObj;
    Obj *heapObj = new Obj();
    thread t([&]{
        stackObj.x++;
        heapObj->x++;
    });
    t.join();
    assert(heapObj->x == 1);
    assert(stackObj.x == 0);
}

原谅我,如果我搞砸了一堆东西,lambda语法对我来说是非常新的。 但希望我正在努力做的是连贯的。 这会像我期望的那样表现吗? 如果没有,我有什么误解?

记忆是记忆。 C ++中的对象占用内存中的某个位置; 该位置可能位于堆栈上或堆上,也可能已静态分配。 对象的位置无关紧要:任何具有引用或指向对象的指针的线程都可以访问该对象。 如果两个线程有​​一个引用或指向该对象的指针,则两个线程都可以访问它。

在您的程序中,您创建一个工作线程(通过构造一个std::thread )来执行您提供的lambda表达式。 因为您通过引用捕获stackObjheapObj (使用[&]捕获默认值),所以lambda引用了这两个对象。

这些对象都位于主线程的堆栈上(请注意, heapObj是一个指针类型对象,位于主线程的堆栈上,指向位于堆上的动态分配对象)。 没有制作这些物品的副本; 相反,您的lambda表达式具有对象的引用。 它直接修改heapObj间接修改stackObj指向的对象。

主线程与工作线程连接后, heapObj->xstackObj.x的值均为1


如果您使用了值捕获默认值( [=] ),则lambda表达式将复制 stackObjheapObj lambda表达式中的表达式stackObj.x++将增加副本 ,并且在main()声明的stackObj将保持不变。

如果按值捕获heapObj ,则只复制指针本身,因此在使用指针的副本时,它仍然指向同一个动态分配的对象。 表达heapObj->x++将解引用该指针,得到Obj你通过创建new Obj()和增加它的价值。 然后,您将在main()的末尾观察到heapObj->x已递增。

(注意,为了修改由value捕获的对象,必须将lambda表达式声明为mutable 。)

我同意James McNellis的观点,即heapObj->xstackObj.x将为1

此外,此代码起作用,因为您在生成线程后立即join 如果你启动了线程,然后在运行时做了更多的工作,一个异常就可以展开堆栈,突然新线程的stackObj无效。 这就是为什么在线程之间共享堆栈内存是一个坏主意,即使它在技术上是可行的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM