Como faço para acessar com segurança o conteúdo de uma propriedade NSARRAY de um thread secundário?
-
19-09-2019 - |
Pergunta
Eu tenho um aplicativo (usando reter/liberação, não gc) que mantém um NSArray
Variável de instância, que é exposta como uma propriedade como sim:
@interface MyObject : NSObject
{
NSArray* myArray;
}
@property (copy) NSArray* myArray;
@end
Quero acessar o conteúdo desta matriz de um fio secundário, que é destacado usando -performSelectorInBackground:withObject:
. É possível e realmente provável que a matriz mude durante a execução do segmento secundário.
No tópico secundário, quero fazer algo assim:
if([self.myArray containsObject:foo])
{
//do stuff
}
Ao ler a documentação do encadeamento, parece que eu deveria poder usar o @synchronized
Diretiva nos acessores como assim:
@implementation MyObject
- (NSArray *)myArray
{
NSArray *result;
@synchronized(self)
{
result = [myArray retain];
}
return [result autorelease];
}
- (void)setMyArray:(NSArray *)aMyArray
{
@synchronized(self)
{
[myArray release];
myArray = [aMyArray copy];
}
}
@end
É tudo o que preciso fazer para garantir a segurança do thread ou é mais complexo?
Atualizar: Posteriormente, encontrei um ótimo artigo no site da Apple que aborda esse problema em profundidade: http://developer.apple.com/mac/library/technotes/tn2002/tn2059.html
Solução
Seu código acima o protege de definir a matriz simultaneamente ou obter a matriz enquanto outro está configurando -o. Como é uma matriz não mutável, isso protege a matriz em si muito bem.
No entanto, se "a matriz mudar", você quer querer editar os itens dentro da matriz, ainda poderá ter alguns problemas. Por exemplo, se a matriz foi preenchida com NSMutablestrings, e você teve um tópico que corria:
NSMutableString *foo = [myObject.myArray objectAtIndex:0];
[foo appendString:@"foo"];
e outro que correu
NSMutableString *bar = [myObject.myArray objectAtIndex:0];
[bar appendString:@"bar"];
O acesso à matriz seria seguro (um tópico teria que esperar o outro para acessá -lo), no entanto, o acesso ao ponteiro Foo/Bar (que é o mesmo) não seria, uma vez que ambas as chamadas para 'AppendString' são Fora do bloco @Synchronized.
Se é assim que sua matriz mudará, você precisará sincronizar esses pontos de acesso também. Com mais blocos @Synchronized ou outros tipos de bloqueios. Ver Usando bloqueios