BT

Construindo melhores coleções thread-safe

por Jonathan Allen , traduzido por Carlos Mendonça em 12 Mar 2009 |

Há alguns problemas fudamentais com a maioria das coleçãoes thread-safe. Enquanto as operações individuais são thread-safe, as operações não são geralmente combináveis. Operações comuns como a verficação da contagem de elementos em uma pilha antes de se retirar um item do seu topo (operação “pop”) são perigosas. Há APIs que tentam combinar operações como o .NET 4’s Coordination Data Structures, mas que acabam disponibilzando métodos desajeitados como o TryDequeue.

Outra tentativa foi observada nas coleções do .NET 1. Ao invés de fazer travas (locks) internos, elas foram expostas através da propriedade SyncRoot. Apesar de SyncRoot continuar sendo o nome padrão para objetos de sincronização, o pattern SyncRoot/Wrapper foi descontinuado no .NET 2..

Então como criar APIs combináveis que são realmente úteis? Jared Parsons propõe que não se exponha a API diretamente. Ao invés disso, deve-se expor todos os métodos através de um objeto temporário que é criado e só está disponível enquanto o código está em posse de uma trava no objeto. Este objeto temporário é a chave (key) na coleção e apenas seu detentor pode conseguir acesso ao seu conteúdo (value).

Aqui está um exemplo de uma fila thread-safe do Jared Parson:

static void Example1(ThreadSafeQueue queue) {
using (var locked = queue.Lock()) {
if (locked.Count > 0) {
var first = locked.Dequeue();
}
}
}

O objeto chamado locked não é thread-safe por si mesmo e espera-se que os desenvolvedores façam a implementação correta ao utilizá-lo dentro de um bloco using. Mas contanto que eles obedeçam esta regra simples, operações dentro do bloco using serão thread-safe. O Jared comenta sobre isso:

Assim como na maioria das arquiteturas thread-safe, há vários de se utilizar este código incorretamente

  1. Utilizar uma instância de ILockedQueue após ela ter sido encerrada. Este erro já é considerado um tabu e pode-se confiar no conhecimento dos desenvolvedores e acreditar que ele não será cometido. Além disso, ferramentas de análise estática de código como a FxCop vão indicar isto como um erro. Se o desenvolvedor tiver um pouco mais de rigor, isso pode-se prevenir que ele não acontecerá. Basta simplesmente adicionar um flag “disposed” e verificá-lo na entrada de qualquer método.
  2. É possível que o desenvolvedor mantenha os valores internos da coleção, como a contagem entre as chamados de travamento (lock) e utilizá-los mais tarde para fazer suposições imprecisas sobre o estado da coleção.
  3. Se o desenvolvedor não descartar a instância do ILockedQueue, ela ficará travada para sempre. Felizmente, o FxCop é capaz de indicar isso como um erro uma vez que é uma implementação da IDisposable. Entretanto, essa verificação não é a prova de falhas.
  4. Nada diz ao usuário “por favor, utilize o IlockedQueue apenas por um período curto de tempo”. Uma IDisposable por si só transmite esta idéia, mas certamente isso não é perfeito.
  5. A implementação do ILockedQueue não é thread-safe. Idealmente, os desenvolvedores não deveriam passar instâncias de uma IDisposable entre threads, mas isso é algo a se pensar.

 

Avalie esse artigo

Relevância
Estilo/Redação

Olá visitante

Você precisa cadastrar-se no InfoQ Brasil ou para enviar comentários. Há muitas vantagens em se cadastrar.

Obtenha o máximo da experiência do InfoQ Brasil.

Dê sua opinião

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão
Comentários da comunidade

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão

Dê sua opinião
Feedback geral
Bugs
Publicidade
Editorial
Marketing
InfoQ Brasil e todo o seu conteúdo: todos os direitos reservados. © 2006-2016 C4Media Inc.
Política de privacidade
BT

We notice you’re using an ad blocker

We understand why you use ad blockers. However to keep InfoQ free we need your support. InfoQ will not provide your data to third parties without individual opt-in consent. We only work with advertisers relevant to our readers. Please consider whitelisting us.