Não preciso finalizar o encadeamento corretamente ou fazê-lo responder a um comando "encerrar". Estou interessado em encerrar o thread com força usando C ++ 11 puro.
c++
multithreading
c++11
Alexander V
fonte
fonte
Respostas:
Você pode ligar
std::terminate()
de qualquer segmento e o segmento ao qual você está se referindo terminará com força.Você pode organizar
~thread()
a execução no objeto do encadeamento de destino, sem interferirjoin()
nemdetach()
nesse objeto. Isso terá o mesmo efeito que a opção 1.Você pode criar uma exceção que possui um destruidor que lança uma exceção. E, em seguida, organize o encadeamento de destino para lançar essa exceção quando for finalizada com força. A parte complicada dessa questão é conseguir que o thread de destino lance essa exceção.
As opções 1 e 2 não vazam recursos intraprocessos, mas encerram todos os encadeamentos.
A opção 3 provavelmente vazará recursos, mas é parcialmente cooperativa, pois o encadeamento de destino precisa concordar em lançar a exceção.
Não há uma maneira portátil no C ++ 11 (que eu saiba) de matar não cooperativamente um único thread em um programa com vários threads (ou seja, sem matar todos os threads). Não havia motivação para projetar esse recurso.
A
std::thread
pode ter esta função de membro:Você pode usar isso para chamar uma função dependente do SO para fazer o que quiser. Por exemplo, nos sistemas operacionais da Apple, essa função existe e
native_handle_type
é apthread_t
. Se você for bem-sucedido, provavelmente vazará recursos.fonte
std::terminate
nem chama destruidores estáticos nem libera buffers de saída; portanto, a ordem na qual os recursos são liberados não é bem definida, nem você tem garantia de que qualquer dado seja visível ao usuário ou gravado no armazenamento permanente, ou mesmo consistente e completo.exit()
ouabort()
para o mesmo efeito geral.A resposta de @Howard Hinnant é correta e abrangente. Mas pode ser mal compreendido se for lido muito rapidamente, porque
std::terminate()
(todo o processo) tem o mesmo nome que o "encerramento" que o @AlexanderVX tinha em mente (1 thread).Resumo: "encerre 1 segmento + com força (o segmento de destino não coopera) + C ++ 11 puro = De jeito nenhum."
fonte
std::terminate()
resposta é como uma história clássica de Djinn travessa; cumpre tudo o que o OP deseja, por carta, embora provavelmente não da maneira que ele quis dizer . O humor discreto me fez sorrir. :-)Esta questão realmente tem uma natureza mais profunda e um bom entendimento dos conceitos de multithreading em geral fornecerá informações sobre este tópico. De fato, não existe nenhum idioma ou sistema operacional que ofereça facilidades para o término abrupto do encadeamento assíncrono sem aviso para não usá-los. E todos esses ambientes de execução aconselham fortemente o desenvolvedor ou mesmo exigem a criação de aplicativos multithreading com base no encerramento de encadeamento cooperativo ou síncrono. A razão para essas decisões e conselhos comuns é que todas elas são construídas com base no mesmo modelo geral de multithreading.
Vamos comparar os conceitos de multiprocessamento e multithreading para entender melhor as vantagens e limitações do segundo.
O multiprocessamento assume a divisão de todo o ambiente de execução em um conjunto de processos completamente isolados, controlados pelo sistema operacional. O processo incorpora e isola o estado do ambiente de execução, incluindo a memória local do processo e os dados dentro dele e todos os recursos do sistema, como arquivos, soquetes, objetos de sincronização. O isolamento é uma característica criticamente importante do processo, porque limita a propagação de falhas pelas bordas do processo. Em outras palavras, nenhum processo pode afetar a consistência de qualquer outro processo no sistema. O mesmo vale para o comportamento do processo, mas da maneira menos restrita e mais desfocada. Nesse ambiente, qualquer processo pode ser morto em qualquer momento "arbitrário", porque primeiro cada processo é isolado;
Por outro lado, o multithreading pressupõe a execução de vários threads no mesmo processo. Mas todos esses threads compartilham a mesma caixa de isolamento e não há nenhum controle do sistema operacional sobre o estado interno do processo. Como resultado, qualquer encadeamento pode alterar o estado do processo global e corrompê-lo. No mesmo momento, os pontos em que o estado do encadeamento é conhecido por ser seguro para eliminar completamente um encadeamento dependem da lógica do aplicativo e não são conhecidos nem pelo sistema operacional nem pelo tempo de execução da linguagem de programação. Como resultado, o término do encadeamento no momento arbitrário significa matá-lo no ponto arbitrário de seu caminho de execução e pode facilmente levar à corrupção de dados em todo o processo, memória e manipular vazamentos,
Devido a isso, a abordagem comum é forçar os desenvolvedores a implementar o término de encadeamento síncrono ou cooperativo, onde um encadeamento pode solicitar outro término de encadeamento e outro encadeamento em ponto bem definido pode verificar essa solicitação e iniciar o procedimento de desligamento a partir do estado bem definido com a liberação de todos os recursos globais do sistema e recursos locais do processo de maneira segura e consistente.
fonte
Dicas para usar a função dependente do SO para finalizar o encadeamento C ++:
std::thread::native_handle()
só pode obter o tipo de identificador nativo válido do encadeamento antes de chamarjoin()
oudetach()
. Depois disso,native_handle()
retorna 0 -pthread_cancel()
irá coredump.Para chamar efetivamente a função de encerramento de encadeamento nativo (por exemplo
pthread_cancel()
), você precisa salvar o identificador nativo antes de chamarstd::thread::join()
oustd::thread::detach()
. Para que seu terminador nativo sempre tenha um identificador nativo válido para usar.Mais explicações, consulte: http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread .
fonte
Eu acho que o segmento que precisa ser eliminado está em qualquer tipo de modo de espera ou está fazendo algum trabalho pesado. Eu sugeriria usar uma maneira "ingênua".
Defina alguns booleanos globais:
Coloque o seguinte código (ou similar) em vários pontos-chave, de maneira que faça com que todas as funções na pilha de chamadas retornem até que o encadeamento termine naturalmente:
Em seguida, para interromper o encadeamento de outro encadeamento (principal):
fonte