Czy @synchronized nie używa „blokady” i „odblokowania” do osiągnięcia wzajemnego wykluczenia? Jak to się wtedy blokuje / odblokowuje?
Wyjście następującego programu to tylko „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
źródło
źródło
lock
Obiekt jest tworzony na każde wezwanie, więc nigdy nie będzie to przypadek, gdzie jeden@synchronized
zamki blokują inny. A to oznacza, że nie ma wzajemnego wykluczenia.) Oczywiście powyższy przykład wykonuje operacjęmain
, więc i tak nie ma co wykluczyć, ale nie należy ślepo kopiować tego kodu w innym miejscu.Odpowiedzi:
Synchronizacja na poziomie języka Objective-C wykorzystuje mutex, podobnie jak
NSLock
robi to. Semantycznie istnieją pewne niewielkie różnice techniczne, ale zasadniczo poprawne jest myślenie o nich jako o dwóch oddzielnych interfejsach zaimplementowanych na wspólnej (bardziej prymitywnej) jednostce.W szczególności
NSLock
masz blokadę jawną, podczas gdy@synchronized
masz ukrytą blokadę związaną z obiektem, którego używasz do synchronizacji. Zaletą blokowania na poziomie języka jest to, że kompilator to rozumie, więc może poradzić sobie z problemami z zakresu, ale mechanicznie zachowują się w zasadzie tak samo.Możesz pomyśleć o
@synchronized
przepisaniu kompilatora:przekształca się w:
Nie jest to do końca poprawne, ponieważ rzeczywista transformacja jest bardziej złożona i korzysta z blokad rekurencyjnych, ale powinna mieć sens.
źródło
W Objective-C
@synchronized
blok obsługuje automatycznie blokowanie i odblokowywanie (a także możliwe wyjątki). Środowisko wykonawcze dynamicznie generuje NSRecursiveLock, który jest powiązany z obiektem, na którym synchronizujesz. Ta dokumentacja Apple wyjaśnia to bardziej szczegółowo. Dlatego nie widzisz komunikatów dziennika z podklasy NSLock - obiekt, na którym synchronizujesz może być czymkolwiek, nie tylko NSLock.Zasadniczo
@synchronized (...)
jest to wygodna konstrukcja, która usprawnia kod. Jak większość uproszczonych abstrakcji, wiąże się to z narzutem (pomyśl o tym jako o ukrytym koszcie) i dobrze jest o tym wiedzieć, ale surowa wydajność prawdopodobnie nie jest najważniejszym celem przy stosowaniu takich konstrukcji.źródło
Tak właściwie
przekształca się bezpośrednio w:
Ten interfejs API jest dostępny od iOS 2.0 i importowany przy użyciu ...
źródło
@synchronized
blok domyślnie dodaje procedurę obsługi wyjątków do chronionego kodu. Ta funkcja obsługi automatycznie zwalnia muteks w przypadku zgłoszenia wyjątku”.Implementacja @synchronized przez Apple jest oprogramowaniem typu open source i można go znaleźć tutaj . Mike Ash napisał dwa naprawdę interesujące posty na ten temat:
W skrócie ma tabelę, która mapuje wskaźniki obiektów (używając ich adresów pamięci jako kluczy) na
pthread_mutex_t
blokady, które są blokowane i odblokowywane w razie potrzeby.źródło
Po prostu łączy semafor z każdym obiektem i używa go.
źródło