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

Mic*_*rst 20 c++ memory heap stack multithreading

我是C++新线程的新手,我试图清楚地了解线程之间如何共享/不共享内存.我正在使用std::threadC++ 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);
}
Run Code Online (Sandbox Code Playgroud)

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

Jam*_*lis 28

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

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

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

主线程后加入与工作线程,都heapObj->xstackObj.x具有的价值1.


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

如果捕获heapObjby值,则只复制指针本身,因此在使用指针的副本时,它仍然指向同一个动态分配的对象.该表达式heapObj->x++将取消引用该指针,从而产生Obj您创建的new Obj(),并增加其值.然后你会在结束时观察main()heapObj->x它已经增加了.

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

  • 该问题的接受答案表明"每个线程都有一个私有堆栈." 这是事实,但是_private_意味着"只有拥有堆栈的线程才能创建和销毁它上面的对象." 这并不意味着"没有其他线程可以访问这个内存." (5认同)
  • @MichaelDorst:每个线程都有自己的堆栈,是的.只有拥有堆栈的线程才可以在该堆栈上分配内存.因此,在您的程序中,主线程和工作线程都有自己独立的堆栈.但是,没有什么能阻止线程与另一个线程共享指针或对它在自己的堆栈上分配的对象的引用.这正是你在这里所做的:主线程在其堆栈上创建一个`Obj`对象,然后与工作线程共享对该对象的引用.然后两个线程都可以访问该对象. (4认同)
  • 如果“记忆就是记忆”,这到底是怎么回事?http://stackoverflow.com/questions/1665419/do-threads-share-the-heap (2认同)