Apartamentos multithreaded
Em um modelo de apartamento multithreaded, todos os threads no processo que foram inicializados como free-threaded residem em um único apartamento. Portanto, não é necessário fazer marshaling entre threads. Os threads não precisam recuperar e expedir mensagens porque COM não usa mensagens de janela neste modelo.
Chamadas para métodos de objetos no apartamento multithreaded podem ser executadas em qualquer thread no apartamento. Não há serialização de chamadas; muitas chamadas podem ocorrer para o mesmo método ou para o mesmo objeto simultaneamente. Os objetos criados no apartamento multithreaded devem ser capazes de lidar com chamadas em seus métodos de outros threads a qualquer momento.
Como as chamadas a objetos não são serializadas de forma alguma, a simultaneidade de objetos multithreaded oferece o melhor desempenho e aproveita o melhor hardware multiprocessador para chamadas entre threads, entre processos e entre máquinas. Isso significa, no entanto, que o código para objetos deve fornecer sincronização em suas implementações de interface, normalmente por meio do uso de primitivos de sincronização, como objetos de evento, seções críticas, mutexes ou semáforos, que são descritos posteriormente nesta seção. Além disso, como o objeto não controla o tempo de vida dos threads que o acessam, nenhum estado específico do thread pode ser armazenado no objeto (no armazenamento local do thread).
A seguir estão algumas considerações importantes sobre a sincronização de apartamentos multithreaded:
- O COM fornece sincronização de chamadas somente para apartamentos de thread único.
- Os apartamentos multithreaded não recebem chamadas ao fazer chamadas (no mesmo thread).
- Os apartamentos multithreaded não podem fazer chamadas sincronizadas por entrada.
- As chamadas assíncronas são convertidas em chamadas síncronas em apartamentos multithread.
- O filtro de mensagem não é chamado para nenhum thread em um apartamento multithreaded.
Para inicializar um thread como de thread livre, chame CoInitializeEx, especificando COINIT_MULTITHREADED. Para obter informações sobre o threading do servidor em processo, consulte In-Process Problemas de Threading do Servidor.
Vários clientes podem chamar simultaneamente, de threads diferentes, um objeto que dá suporte ao threading livre. Em servidores fora de processo de thread livre, o COM, por meio do subsistema RPC, cria um pool de threads no processo do servidor e uma chamada de cliente (ou várias chamadas de cliente) pode ser entregue por qualquer um desses threads a qualquer momento. Um servidor fora de processo também deve implementar a sincronização em sua fábrica de classes. Objetos em processo de thread livre podem receber chamadas diretas de vários threads do cliente.
O cliente pode fazer com que o COM funcione em vários threads. Todos os threads pertencem ao mesmo apartamento multithreaded. Os ponteiros de interface são passados diretamente de thread para thread dentro de um apartamento multithreaded, de modo que os ponteiros de interface não são marshalados entre seus threads. Os filtros de mensagem (implementações de IMessageFilter) não são usados em apartamentos multithreaded. O thread do cliente será suspenso quando fizer uma chamada COM para objetos fora do apartamento e será retomado quando a chamada for retornada. As chamadas entre processos ainda são tratadas pelo RPC.
Os threads inicializados com o modelo de thread livre devem implementar sua própria sincronização. Conforme mencionado anteriormente nesta seção, o Windows habilita essa implementação por meio dos seguintes primitivos de sincronização:
- Os objetos de evento fornecem uma maneira de sinalizar um ou mais threads de que ocorreu um evento. Qualquer thread dentro de um processo pode criar um objeto de evento. Um identificador para o evento é retornado pela função de criação de eventos, CreateEvent. Depois que um objeto de evento for criado, os threads com um identificador para o objeto poderão aguardar antes de continuar a execução.
- Seções críticas são usadas para uma seção de código que requer acesso exclusivo a algum conjunto de dados compartilhados antes de serem executadas e que são usadas apenas pelos threads em um único processo. Uma seção crítica é como uma catraca pela qual apenas um thread por vez pode passar, funcionando da seguinte maneira:
- Para garantir que não mais de um thread por vez acesse dados compartilhados, o thread primário de um processo aloca uma estrutura de dados CRITICAL_SECTION global e inicializa seus membros. Um thread que entra em uma seção crítica chama a função EnterCriticalSection e modifica os membros da estrutura de dados.
- Um thread que tenta inserir uma seção crítica chama EnterCriticalSection que verifica se a estrutura de dados CRITICAL_SECTION foi modificada. Nesse caso, outro thread está atualmente na seção crítica e o thread subsequente é colocado em suspensão. Um thread que deixa uma seção crítica chama LeaveCriticalSection, que redefine a estrutura de dados. Quando um thread deixa uma seção crítica, o sistema ativa um dos threads de suspensão, que entra na seção crítica.
- O Mutexes executa a mesma função que uma seção crítica, exceto que o mutex é acessível para threads em execução em processos diferentes. Possuir um objeto mutex é como ter o chão em um debate. Um processo cria um objeto mutex chamando a função CreateMutex, que retorna um identificador. O primeiro thread que solicita um objeto mutex obtém a propriedade dele. Quando o thread tiver terminado com o mutex, a propriedade passará para outros threads por várias etapas.
- Semáforos são usados para manter uma contagem de referência em algum recurso disponível. Um thread cria um semáforo para um recurso chamando a função CreateSemaphore e passando um ponteiro para o recurso, uma contagem de recursos inicial e a contagem máxima de recursos. Essa função retorna um identificador. Um thread que solicita um recurso passa seu identificador de semáforo em uma chamada para a funçãowaitForSingleObject. O objeto semáforo sonda o recurso para determinar se ele está disponível. Nesse caso, o semáforo diminui a contagem de recursos e ativa o thread de espera. Se a contagem for zero, o thread permanecerá dormindo até que outro thread libere um recurso, fazendo com que o semáforo incremente a contagem para um.
Tópicos relacionados
-
problemas de threading do servidor In-Process
-
Single-Threaded e de Comunicação Multithreaded
-
de apartamentosSingle-Threaded