samp programacion paralela open ejemplos distribuida descargar c++ multithreading memory stack heap

programacion - Compartir memoria entre hilos de C++



programacion paralela en c (2)

Soy nuevo en subprocesos en C ++, y estoy tratando de obtener una imagen clara de cómo se comparte / no se comparte la memoria entre subprocesos. Estoy usando std::thread con C ++ 11. Por lo que he leído en otras preguntas de SO, la memoria de la pila es propiedad de un solo hilo y la memoria del montón se comparte entre los hilos. Por lo que creo que entiendo sobre la pila y el montón, lo siguiente debería ser cierto:

#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); }

perdóname si jodí un montón de cosas, la sintaxis lambda es muy nueva para mí. Pero espero que lo que estoy tratando de hacer sea coherente. ¿Funcionaría como espero? Y si no, ¿qué estoy malinterpretando?


Estoy de acuerdo con James McNellis en que heapObj->x stackObj.x serán 1 .

Además, este código solo funciona porque te join inmediatamente después de generar el hilo. Si inició el subproceso y luego hizo más trabajo mientras se ejecuta, una excepción podría desenrollar la pila y, de repente, el nuevo stackObj del stackObj no es válido. Es por eso que compartir memoria de pila entre hilos es una mala idea, incluso si es técnicamente posible.


La memoria es la memoria. Un objeto en C ++ ocupa alguna ubicación en la memoria; esa ubicación puede estar en una pila o en el montón, o puede haber sido asignada estáticamente. No importa dónde se encuentre el objeto: cualquier subproceso que tenga una referencia o un puntero al objeto puede acceder al objeto. Si dos subprocesos tienen una referencia o un puntero al objeto, ambos subprocesos pueden acceder a él.

En su programa, crea un subproceso de trabajo (mediante la construcción de un std::thread ) que ejecuta la expresión lambda que le proporcionó. Debido a que captura tanto stackObj como heapObj por referencia (usando la captura por defecto [&] ), lambda tiene referencias a ambos objetos.

Esos objetos están ubicados en la pila del hilo principal (tenga en cuenta que heapObj es un objeto de tipo puntero que se encuentra en la pila del hilo principal y apunta a un objeto asignado dinámicamente que se encuentra en el montón). No se hacen copias de estos objetos; más bien, su expresión lambda tiene referencias a los objetos. Modifica el stackObj directamente y modifica el objeto apuntado por heapObj indirectamente.

Después de que el hilo principal se une con el hilo trabajador, tanto heapObj->x como stackObj.x tienen un valor de 1 .

Si hubiera usado el valor predeterminado de captura ( [=] ), su expresión lambda habría copiado tanto stackObj como heapObj . La expresión stackObj.x++ en la expresión lambda incrementaría la copia , y el stackObj que declara en main() no se modificará.

Si captura el heapObj por valor, solo se copia el puntero, por lo que mientras se usa una copia del puntero, aún apunta al mismo objeto asignado dinámicamente. La expresión heapObj->x++ referencia a ese puntero, generando el Obj que creó a través de un new Obj() e incrementaría su valor. Luego observará al final de main() que heapObj->x se ha incrementado.

(Tenga en cuenta que para modificar un objeto capturado por valor, la expresión lambda debe declararse mutable ).