Pergunta

Eu preciso fazer um ArrayList de seguro ArrayLists fio. Eu também não pode ter o making cliente alterações à coleção. Será que o unmodifiable invólucro tornam-thread-safe ou eu preciso dois invólucros na coleção?

Foi útil?

Solução

Depende. O invólucro só irá impedir alterações para a coleção que envolve, não para os objetos na coleção. Se você tem um ArrayList de ArrayLists, a Lista global, bem como cada uma de suas listas de elementos precisam ser embrulhado separadamente, e você também pode ter que fazer algo para o conteúdo dessas listas. Finalmente, você tem que ter certeza que os objetos lista original não são alterados, uma vez que o wrapper só impede mudanças através da referência invólucro, não o objeto original.

Você não precisa o wrapper sincronizado neste caso.

Outras dicas

Em um tópico relacionado - Eu já vi várias respostas sugerindo usando coleção sincronizada a fim de alcançar a segurança do thread. Usando a versão sincronizada de uma coleção não torná-lo "thread-safe" - embora cada operação (inserção, contagem etc.) é protegido por mutex na combinação de duas operações não há nenhuma garantia de que eles iriam executar atomicamente. Por exemplo, o seguinte código não é thread-safe (mesmo com uma fila sincronizada):

if(queue.Count > 0)
{
   queue.Add(...);
}

O wrapper unmodifiable só impede alterações na estrutura da lista que se aplica. Se esta lista contém outras listas e você tem tópicos tentando modificar estas listas aninhadas, então você não estão protegidos contra riscos modificação concorrente.

De olhar para a fonte de coleções, parece que não modificável faz não torná-lo sincronizado.

static class UnmodifiableSet<E> extends UnmodifiableCollection<E>
                 implements Set<E>, Serializable;

static class UnmodifiableCollection<E> implements Collection<E>, Serializable;

os invólucros de classe sincronizados ter um objeto mutex para praticar as partes sincronizados, então parece que você precisa usar tanto para obter ambos. Ou rolar seus próprios!

Eu acredito que porque as lojas de mensagens publicitárias unmodifiableList o ArrayList para um campo final, quaisquer métodos de leitura no invólucro verá a lista como era quando o invólucro foi construído, desde que a lista não é modificado após o wrapper é criado , e enquanto os ArrayLists mutáveis ??dentro do invólucro não são modificados (qual o invólucro não pode proteger contra).

Será thread-safe se a visão não modificável é publicado de forma segura, eo original modificável nunca é sempre modificada (incluindo todos os objetos recursivamente contidos na coleção!) Após a publicação da visão não modificável.

Se você quiser manter modificando o original, então você pode criar uma cópia defensiva do gráfico do objeto de sua coleção e retornar uma visão não modificável isso, ou usar uma lista inerentemente thread-safe, para começar, e retornar um visão não modificável disso.

Você não pode retornar um unmodifiableList (synchonizedList (theList)) se você ainda pretende acesso theList unsynchronized depois; Se o estado mutável é compartilhado entre vários segmentos, em seguida, todas tópicos deve sincronizar no mesma fechaduras quando eles acessarem esse estado.

Um objeto imutável é por segmento seguro definição (supondo que ninguém mantém referências aos coleções originais), de modo que a sincronização é não necessário.

Embalagem ArrayList exterior usando Collections.unmodifiableList () impede que o cliente mudar o seu conteúdo (e, portanto, torna rosca seguro), mas os ArrayLists internos ainda são mutáveis.

Embalagem as ArrayLists internos usando Collections.unmodifiableList () também impede que o cliente mudar seu conteúdo (e, portanto, torna-os thread-safe), que é o que você precisa.

Deixe-nos saber se esta solução causa problemas (sobrecarga, uso de memória, etc.); outras soluções podem ser aplicadas para o seu problema. :)

EDIT: Claro, se as listas são modificados não são thread-safe. Eu assumi há mais edições deviam ser feitas.

Não tenho certeza se eu entendi o que você está tentando fazer, mas eu diria que a resposta na maioria dos casos é "Não".

Se você configurar um ArrayList de ArrayList e ambos, as listas externas e internas não pode ser alterado após a criação (e durante a criação de apenas um segmento terão acesso a qualquer listas internas e externas), eles são, provavelmente, o segmento de seguros por um invólucro (se ambos, listas exteriores e interiores são enrolados de tal maneira que uma sua modificação é impossível). Todas as operações somente leitura em ArrayLists são mais susceptíveis thread-safe. No entanto, a Sun não garantia -los para ser thread-safe (também não para operações somente leitura), por isso mesmo que pode funcionar agora, poderia quebrar no futuro (se a Sun cria alguns internos cache de dados para acesso mais rápido, por exemplo).

Esta é neccessary se:

  1. Há ainda uma referência à lista modificável originais.
  2. A lista vai possivelmente ser acessado embora um iterador.

Se você pretende ler a partir do ArrayList pelo índice só você poderia supor que esta é thread-safe.

Em caso de dúvida, escolheu o wrapper sincronizado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top