shared_memory track: controle o resource tracker

Publicado em: 16/10/2026
Tempo de leitura: 6 minutos
CPU e módulos de memória representando shared_memory track no Python

O parâmetro track de multiprocessing.shared_memory.SharedMemory resolve um problema importante em aplicações Python que compartilham memória entre processos independentes. Ele define se o segmento deve ser registrado no resource tracker do multiprocessing, componente responsável por limpar recursos que poderiam permanecer no sistema após o fim dos processos. Parece um detalhe pequeno, mas uma escolha errada pode remover a memória cedo demais, gerar avisos de vazamento ou deixar segmentos órfãos.

Neste guia, você vai entender quando usar track=True, quando usar track=False, como combinar close() e unlink(), quais diferenças existem entre processos criados pela mesma família e processos iniciados separadamente, além de padrões seguros para Linux, macOS e Windows.

O que é memória compartilhada

Memória compartilhada permite que dois ou mais processos acessem a mesma região de bytes sem serializar grandes objetos a cada troca. Isso é útil em processamento numérico, visão computacional, pipelines de dados e serviços que trabalham com buffers extensos. Em vez de copiar uma matriz de centenas de megabytes por uma fila, um processo cria o segmento e outros processos abrem o mesmo nome.

from multiprocessing import shared_memory

shm = shared_memory.SharedMemory(create=True, size=1024)
try:
    shm.buf[:4] = b"PYTH"
finally:
    shm.close()
    shm.unlink()

O método close() fecha o descritor local. O método unlink() solicita a remoção do nome do segmento. Em sistemas POSIX, o conteúdo pode continuar disponível para processos que já o abriram até que o último descritor seja fechado. No Windows, a remoção ocorre quando todos os identificadores são fechados.

Para que serve o parâmetro track

Com track=True, o segmento é registrado no rastreador de recursos do multiprocessing. Se o processo responsável terminar sem executar a limpeza, o rastreador tenta remover o recurso. Esse comportamento é conveniente quando todos os processos pertencem à mesma árvore criada por multiprocessing, porque eles normalmente compartilham uma infraestrutura coordenada.

Com track=False, o objeto não é registrado nesse rastreador. A aplicação passa a assumir integralmente a responsabilidade por definir quem chama unlink(). Isso é especialmente relevante quando processos são iniciados por shells, supervisores, containers ou serviços diferentes.

O problema dos processos independentes

Imagine um produtor iniciado pelo systemd e um consumidor executado manualmente. Ambos abrem o mesmo segmento. Se cada processo possuir seu próprio resource tracker e usar track=True, o primeiro processo que terminar pode fazer o rastreador remover o segmento, embora o outro ainda precise que novos consumidores consigam abri-lo. O processo que já mantém um descritor pode continuar trabalhando em alguns sistemas, mas novas aberturas falharão.

Nesse cenário, costuma ser melhor escolher um proprietário explícito. O proprietário cria o segmento, publica seu nome e executa unlink() apenas no encerramento definitivo. Clientes independentes abrem o segmento com track=False e chamam somente close().

from multiprocessing import shared_memory

# Cliente independente
shm = shared_memory.SharedMemory(
    name="dados_academify",
    create=False,
    track=False,
)
try:
    dados = bytes(shm.buf[:128])
finally:
    shm.close()

Padrão com proprietário único

Um desenho robusto define claramente o ciclo de vida. O processo proprietário cria o segmento, grava uma versão de protocolo no cabeçalho, mantém um bloqueio ou mecanismo de coordenação e remove o recurso apenas depois que os clientes encerram.

from multiprocessing import shared_memory

shm = shared_memory.SharedMemory(
    name="cache_python",
    create=True,
    size=4096,
    track=True,
)
try:
    shm.buf[:8] = b"CACHE001"
    input("Pressione Enter para encerrar")
finally:
    shm.close()
    shm.unlink()

O proprietário pode usar track=True como proteção adicional, desde que os clientes independentes usem track=False. Assim, apenas o ciclo de vida do proprietário participa da limpeza automática.

Processos da mesma aplicação

Quando os workers são criados por multiprocessing.Process, Pool ou outro mecanismo coordenado pela mesma aplicação, track=True geralmente é a opção natural. Ainda assim, não confie somente no encerramento automático. Use blocos try/finally, registre quem é o dono e teste interrupções.

Também é útil comparar com outros recursos de concorrência em artigos como multiprocessing no Python, queue no Python, mmap no Python e contextvars no Python. Cada ferramenta tem um modelo diferente de propriedade, sincronização e limpeza.

Essa distinção merece atenção. close() libera apenas o acesso daquele objeto local. Ele não remove necessariamente o segmento do sistema. unlink() remove o nome e impede novas conexões, mas não deve ser chamado indiscriminadamente por todos os participantes.

Uma regra prática é: todos os processos chamam close(); somente o proprietário chama unlink(). Quando há failover, documente como um novo proprietário é eleito e como detectar segmentos antigos com segurança.

Compatibilidade no Windows

No Windows, o parâmetro de rastreamento tem efeito diferente porque o próprio sistema remove a memória quando todos os identificadores são fechados. Mesmo assim, escrever código portátil exige cuidado. Não presuma que o comportamento de remoção será idêntico em Linux. Teste o ciclo de vida em cada plataforma suportada e evite colocar unlink() em clientes genéricos.

Validação e formato do buffer

Memória compartilhada não transporta metadados de alto nível automaticamente. Defina um cabeçalho com versão, tamanho, estado e checksum. Antes de ler, confirme que o produtor terminou a gravação. Para estruturas numéricas, combine o buffer com memoryview, struct ou NumPy, mas valide dimensões e tipo.

import struct

versao, tamanho = struct.unpack_from("!II", shm.buf, 0)
if versao != 1:
    raise RuntimeError("Versão incompatível")
if tamanho > len(shm.buf) - 8:
    raise ValueError("Tamanho inválido")

Sincronização

O parâmetro track não oferece bloqueio. Ele cuida apenas do rastreamento do recurso. Para evitar leituras durante uma gravação, use locks, semáforos, eventos, filas de controle ou protocolos de versão. Um padrão simples grava os dados, calcula um checksum e só então altera um campo de estado de “gravando” para “pronto”.

Tratamento de falhas

Considere encerramento abrupto, reinício do produtor e clientes atrasados. Ao iniciar, o proprietário pode verificar se o nome já existe. Não remova automaticamente um segmento desconhecido: ele pode pertencer a outra instância ativa. Use nomes com namespace, identificador da aplicação e ambiente.

Em ambientes com containers, observe também o namespace de IPC. Dois containers podem não enxergar o mesmo segmento, dependendo da configuração. Para detalhes oficiais, consulte a documentação de multiprocessing.shared_memory e a documentação do multiprocessing.

Testes recomendados

Crie testes que iniciem produtor e consumidor, encerrem cada um em ordens diferentes e tentem abrir o segmento novamente. Teste também exceções antes de unlink(), finalização por sinal e reinício. Em Linux, ferramentas como ls /dev/shm ajudam a identificar recursos residuais durante desenvolvimento, mas não devem substituir uma estratégia de ciclo de vida.

Erros comuns

Os erros mais frequentes são permitir que todo cliente execute unlink(), usar track=True em processos independentes sem entender os trackers separados, esquecer close(), armazenar dados sem cabeçalho e tratar memória compartilhada como se fosse thread-safe. Outro erro é reutilizar um nome fixo sem verificar versão e proprietário.

Checklist de produção

Defina um único proprietário, escolha track conforme a topologia dos processos, feche todos os descritores, remova o segmento apenas no fim correto, valide tamanho e versão, sincronize escritores e leitores, monitore recursos órfãos e teste nas plataformas reais.

Conclusão

O parâmetro track não muda como os bytes são compartilhados; ele muda quem participa da limpeza automática. Use track=True quando a família de processos é coordenada pelo multiprocessing e compartilha o mesmo modelo de ciclo de vida. Use track=False em clientes independentes quando existe um proprietário externo responsável pela remoção. Com propriedade explícita, close(), unlink(), sincronização e validação, a memória compartilhada se torna rápida e previsível.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Unidade de armazenamento de dados representando compactação com compression.zstd no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    compression.zstd: streams e compressão segura

    Aprenda compression.zstd no Python para compactar arquivos e dados com velocidade, streaming, dicionários e segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    15/10/2026
    Código em tela para diagnóstico de processos com sys.remote_exec no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    sys.remote_exec: diagnostique processos Python

    Aprenda sys.remote_exec no Python para diagnosticar processos em execução com scripts controlados, segurança e boas práticas.

    Ler mais

    Tempo de leitura: 6 minutos
    15/10/2026
    Código Python e configuração de variáveis de ambiente com os.reload_environ
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    os.reload_environ: riscos com threads e ambiente

    Aprenda os.reload_environ no Python para atualizar variáveis de ambiente alteradas externamente, validar configurações e evitar problemas com threads.

    Ler mais

    Tempo de leitura: 5 minutos
    14/10/2026
    Código Python representando contextvars.Token e isolamento de contexto assíncrono
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    contextvars.Token: restaure contexto async

    Aprenda contextvars.Token no Python para definir valores temporários, restaurar contextos e isolar dados entre tarefas assíncronas.

    Ler mais

    Tempo de leitura: 6 minutos
    14/10/2026
    Visualização de dados e distribuição estatística para statistics.kde_random no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    statistics.kde_random: gere amostras de uma KDE

    Aprenda statistics.kde_random no Python para gerar amostras a partir de uma distribuição estimada por kernel com controle de suavização, sementes

    Ler mais

    Tempo de leitura: 6 minutos
    13/10/2026
    Ambiente Linux representando namespaces e automação com os.setns no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    os.setns: entre em namespaces Linux com segurança

    Aprenda os.setns no Python para mover processos entre namespaces Linux com segurança, permissões, testes e limpeza adequada.

    Ler mais

    Tempo de leitura: 5 minutos
    13/10/2026