@Synchronized não usa "lock" e "unlock" para obter exclusão mútua? Como ele bloqueia / desbloqueia então?
A saída do programa a seguir é apenas "Hello World".
@interface MyLock: NSLock<NSLocking>
@end
@implementation MyLock
- (id)init {
return [super init];
}
- (void)lock {
NSLog(@"before lock");
[super lock];
NSLog(@"after lock");
}
- (void)unlock {
NSLog(@"before unlock");
[super unlock];
NSLog(@"after unlock");
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MyLock *lock = [[MyLock new] autorelease];
@synchronized(lock) {
NSLog(@"Hello World");
}
[pool drain];
}
objective-c
synchronization
David Lin
fonte
fonte
lock
objeto é criado em todas as chamadas, portanto, nunca haverá um caso em que um@synchronized
bloco bloqueie outro. E isso significa que não há exclusão mútua.) É claro que o exemplo acima está executando a operaçãomain
, portanto não há nada a excluir, mas não se deve copiar cegamente esse código em outro lugar.Respostas:
A sincronização no nível de linguagem Objective-C usa o mutex, assim como
NSLock
faz. Semanticamente, existem algumas pequenas diferenças técnicas, mas é basicamente correto pensar nelas como duas interfaces separadas implementadas sobre uma entidade comum (mais primitiva).Em particular,
NSLock
você tem um bloqueio explícito, enquanto@synchronized
que um bloqueio implícito está associado ao objeto que você está usando para sincronizar. O benefício do bloqueio no nível do idioma é que o compilador o entende para lidar com problemas de escopo, mas mecanicamente eles se comportam basicamente da mesma forma.Você pode pensar
@synchronized
em uma reescrita do compilador:é transformado em:
Isso não é exatamente correto, porque a transformação real é mais complexa e usa bloqueios recursivos, mas deve passar o ponto.
fonte
No Objective-C, um
@synchronized
bloco lida com o bloqueio e desbloqueio (bem como com possíveis exceções) automaticamente para você. O tempo de execução dinamicamente gera essencialmente um NSRecursiveLock associado ao objeto no qual você está sincronizando. Esta documentação da Apple explica mais detalhadamente. É por isso que você não está vendo as mensagens de log da sua subclasse NSLock - o objeto no qual você sincroniza pode ser qualquer coisa, não apenas um NSLock.Basicamente,
@synchronized (...)
é uma construção de conveniência que otimiza seu código. Como a maioria das abstrações simplificadoras, ela tem sobrecarga associada (pense nisso como um custo oculto), e é bom estar ciente disso, mas o desempenho bruto provavelmente não é o objetivo supremo ao usar essas construções de qualquer maneira.fonte
Na realidade
transforma diretamente em:
Esta API está disponível desde o iOS 2.0 e importada usando ...
fonte
@synchronized
bloco adiciona implicitamente um manipulador de exceções ao código protegido. Esse manipulador libera automaticamente o mutex no caso de uma exceção ser lançada".A implementação do @synchronized pela Apple é de código aberto e pode ser encontrada aqui . Mike ash escreveu dois posts realmente interessantes sobre esse assunto:
Em poucas palavras, há uma tabela que mapeia ponteiros de objetos (usando seus endereços de memória como chaves) para
pthread_mutex_t
bloqueios, que são bloqueados e desbloqueados conforme necessário.fonte
Apenas associa um semáforo a cada objeto e o usa.
fonte