É impulso shared_ptr thread-safe?
-
22-08-2019 - |
Pergunta
Eu tenho uma pergunta sobre boost::shared_ptr<T>
.
Há lotes de fio.
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
Se Thread_A não se importam o nowResource
é o mais novo, vai esta parte do código tem problema?
eu quero dizer quando Thread_B não SetResource()
completamente, Thread_A obter um ponto inteligente errado por GetResource()
?
Q2
O que significa thread-safe?
Se eu não se preocupam se o recurso é mais novo, vai a shared_ptr<CResource> nowResource
travar o programa quando o nowResource
é liberado ou se o problema destruir o shared_ptr<CResource>
?
Solução
objetos
shared_ptr
oferecer o mesmo nível de segurança do thread como built-in tipos. Um exemplo pode sershared_ptr
"Ler" (acessado usando apenas const operações) em simultâneo por múltiplos tópicos. diferenteshared_ptr
casos pode ser "escrita com" (Acedido usando operações mutáveis tal comooperator=
ou reset) simultaneamente por vários segmentos (Mesmo quando estas instâncias são cópias, e compartilhar a mesma contagem de referência por baixo.)Quaisquer outros acessos simultâneos resultar em um comportamento indefinido.
Portanto, o seu uso não é seguro, uma vez que utiliza leitura e gravação de m_res
simultânea. Exemplo 3 na documentação impulso também ilustra isso.
Você deve usar um separar mutex que guarda o acesso a m_res
em SetResource
/ GetResource
.
Outras dicas
ofertas boost::shared_ptr<>
um certo nível de segurança do thread. A contagem de referência é manipulado de uma forma thread-safe (a menos que você configure impulso para suporte de threading desativar).
Assim, você pode copiar um shared_ptr
ao redor eo Ref_Count é mantido corretamente. O que você não pode fazer com segurança em vários segmentos é modificar o próprio exemplo shared_ptr
objeto real de vários segmentos (como chamar reset()
sobre ele a partir de múltiplas threads). Portanto, o seu uso não é seguro - você está modificando a instância shared_ptr
real em vários segmentos -. Você vai precisar de ter a sua própria proteção
No meu código, de shared_ptr
são geralmente moradores ou parâmetros passados ??por valor, então não há nenhum problema. Trazê-los de um segmento para outro Eu geralmente uso uma fila thread-safe.
Claro que nada disto endereços a segurança do thread de acessar o objeto apontado pelo shared_ptr
-. Que também é até você
Bem, tr1 :: shared_ptr (que se baseia na boost) documentação conta uma história diferente, o que implica que a gestão dos recursos é o segmento de seguros, ao passo que o acesso ao recurso não é.
" ...
thread-safe
C ++ 0x-únicas características são: rvalue-ref / suporte movimento, alocador de apoio, construtor aliasing, make_shared & allocate_shared. Além disso, os construtores tendo auto_ptr parâmetros são preteridos em modo C ++ 0x.
A seção Segurança de thread da documentação Impulso shared_ptr diz "objetos shared_ptr oferecer o mesmo nível de segurança do thread como tipos built-in." A implementação deve garantir que as atualizações simultâneas para casos shared_ptr separados são ainda correto quando essas instâncias compartilham uma referência contar por exemplo.
shared_ptr A (novo A); shared_ptr b (a);
// Thread 1 // Passe 2
a.reset (); b.reset ();
O objeto alocada dinamicamente deve ser destruído por exatamente um dos tópicos. referências fracas tornar as coisas ainda mais interessantes. O estado compartilhado usado para implementar shared_ptr deve ser transparente para o usuário e invariantes deve ser preservado em todos os momentos. As peças-chave do estado compartilhado são as contagens de referência fortes e fracos. Atualizações para estes necessidade de ser atômica e visível para os tópicos para garantir a limpeza correta do recurso gerenciado (que é, afinal de contas, o trabalho de shared_ptr!) Pode ser necessária a sincronização Memória sistemas multi-processador de modo que as atualizações de referência de contagem e da destruição do recurso gerenciado são livres de corrida.
... "
ver http://gcc.gnu.org/onlinedocs /libstdc++/manual/memory.html#std.util.memory.shared_ptr
m_Res não é threadsafe, pois simultânea de leitura / gravação, Você precisa boost :: função atomic_store / carga para protege-lo.
//--- Example 3 ---
// thread A
p = p3; // reads p3, writes p
// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write
Adicionar, sua classe tem uma condição referências cíclicas; o shared_ptr<CResource> m_Res
não pode ser um membro de CResourceBase
. Você pode usar weak_ptr
vez.