c++ - ¿El subproceso shared_ptr<XXX> es seguro?
boost thread-safety (5)
Tengo una pregunta sobre boost::shared_ptr<T>
.
Hay muchos hilos
using namespace boost;
class CResource
{
// xxxxxx
}
class CResourceBase
{
public:
void SetResource(shared_ptr<CResource> res)
{
m_Res = res;
}
shared_ptr<CResource> GetResource()
{
return m_Res;
}
private:
shared_ptr<CResource> m_Res;
}
CResourceBase base;
//----------------------------------------------
// Thread_A:
while (true)
{
//...
shared_ptr<CResource> nowResource = base.GetResource();
nowResource.doSomeThing();
//...
}
// Thread_B:
shared_ptr<CResource> nowResource;
base.SetResource(nowResource);
//...
Q1
Si a Thread_A no le importa que nowResource
sea el más reciente, ¿tendrá esta parte del código algún problema?
Quiero decir cuando Thread_B no establece SetResource()
completamente, Thread_A obtiene un punto inteligente incorrecto por GetResource()
?
Q2
¿Qué significa thread-safe?
Si no me importa si el recurso es el más nuevo, ¿ shared_ptr<CResource> nowResource
bloqueará el programa cuando se nowResource
o el problema destruirá el shared_ptr<CResource>
?
Agregar, su clase tiene una condición de referencias cíclicas; shared_ptr<CResource> m_Res
no puede ser miembro de CResourceBase
. Puedes usar weak_ptr
en weak_ptr
lugar.
Bueno, la documentación tr1 :: shared_ptr (que se basa en el impulso) cuenta una historia diferente, lo que implica que la administración de recursos es segura para subprocesos, mientras que el acceso al recurso no lo es.
"...
Seguridad de subprocesos
Las características de C ++ 0x son: soporte de rvalue-ref / move, soporte de asignador, constructor de aliasing, make_shared & allocate_shared. Además, los constructores que toman los parámetros auto_ptr están en desuso en el modo C ++ 0x.
La sección Seguridad de subprocesos de la documentación de Boost shared_ptr dice "los objetos shared_ptr ofrecen el mismo nivel de seguridad de subprocesos que los tipos incorporados". La implementación debe garantizar que las actualizaciones concurrentes para separar las instancias de shared_ptr sean correctas incluso cuando esas instancias comparten un recuento de referencia, por ejemplo
shared_ptr a (nuevo A); shared_ptr b (a);
// Hilo 1 // Hilo 2
se establecen(); b.reset ();
El objeto asignado dinámicamente debe ser destruido exactamente por uno de los hilos. Las referencias débiles hacen que las cosas sean aún más interesantes. El estado compartido utilizado para implementar shared_ptr debe ser transparente para el usuario y las invariantes deben conservarse en todo momento. Las piezas clave de estado compartido son los recuentos de referencia fuertes y débiles. Las actualizaciones de estos deben ser atómicas y visibles para todos los hilos para asegurar la limpieza correcta del recurso administrado (¡que es, después de todo, el trabajo de shared_ptr!) En los sistemas multiprocesador, la sincronización de memoria puede ser necesaria para que las actualizaciones de recuento de referencias y la destrucción del recurso administrado no tienen raza.
... "
ver http://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.shared_ptr
De la documentation impulso:
shared_ptr
objetosshared_ptr
ofrecen el mismo nivel de seguridad de subprocesos que los tipos incorporados. Una instancia deshared_ptr
se puede "leer" (accediendo usando solo operaciones const) simultáneamente por múltiples hilos. Diferentes instanciasshared_ptr
pueden ser "escritas en" (accedidas usando operaciones mutables comooperator=
o reset) simultáneamente por múltiples hilos (incluso cuando estas instancias son copias, y comparten el mismo recuento de referencia debajo).Cualquier otro acceso simultáneo da como resultado un comportamiento indefinido.
Por lo tanto, su uso no es seguro, ya que utiliza lectura y escritura simultáneas de m_res
. El ejemplo 3 en la documentación de impulso también lo ilustra.
Debería usar un mutex separado que m_res
el acceso a m_res
en SetResource
/ GetResource
.
boost::shared_ptr<>
ofrece un cierto nivel de seguridad de subprocesos. El recuento de referencias se manipula de forma segura para hilos (a menos que configure boost para deshabilitar el soporte de subprocesos).
Entonces puede copiar un shared_ptr
y el ref_count se mantiene correctamente. Lo que no se puede hacer de manera segura en varios subprocesos es modificar la propia instancia de objeto shared_ptr
desde varios subprocesos (como llamar a reset()
desde varios subprocesos). Por lo tanto, su uso no es seguro; está modificando la instancia de shared_ptr
real en varios hilos; deberá tener su propia protección.
En mi código, shared_ptr
generalmente son locals o parámetros pasados por valor, por lo que no hay problema. Obteniéndolos de un hilo a otro generalmente utilizo una cola segura para subprocesos.
Por supuesto, nada de esto aborda la seguridad de subprocesos para acceder al objeto señalado por shared_ptr
; eso depende de usted.
m_Res no es threadsafe, porque lee / escribe simultáneamente, necesita boost :: atomic_store / load function para protegerlo.
//--- Example 3 ---
// thread A
p = p3; // reads p3, writes p
// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write