Jak @synchronized blokuje / odblokowuje w Objective-C?
Czy @synchronized nie używa "lock" I "unlock", aby osiągnąć wzajemne wykluczenie? Jak to zrobić, aby zablokować / odblokować następnie?
Wynikiem następującego programu jest 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];
}
5 answers
SYNCHRONIZACJA poziomu języka Objective-C wykorzystuje mutex, tak jak robi to NSLock
. 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 z NSLock
masz jawną blokadę, podczas gdy z {[4] } masz ukrytą blokadę związaną z obiektem, którego używasz do synchronizacji. Zaletą blokowania poziomu językowego jest kompilator rozumie to, więc może radzić sobie z problemami z zakresami, ale mechanicznie zachowują się zasadniczo tak samo.
Możesz myśleć o @synchronized
jako o przepisaniu kompilatora:
- (NSString *)myString {
@synchronized(self) {
return [[myString retain] autorelease];
}
}
Przekształca się w:
- (NSString *)myString {
NSString *retval = nil;
pthread_mutex_t *self_mutex = LOOK_UP_MUTEX(self);
pthread_mutex_lock(self_mutex);
retval = [[myString retain] autorelease];
pthread_mutex_unlock(self_mutex);
return retval;
}
To nie jest do końca poprawne, ponieważ rzeczywista transformacja jest bardziej złożona i używa rekurencyjnych blokad, ale powinna uzyskać punkt w poprzek.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-25 23:28:52
W Objective-C, Blok @synchronized
automatycznie blokuje i odblokowuje (jak również możliwe wyjątki). Runtime 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 wiadomości logów z podklasy NSLock - obiekt, na którym synchronizujesz, może być wszystkim, a nie tylko NSLock.
Zasadniczo, @synchronized (...)
jest wygodą skonstruować, że usprawnia swój kod. Podobnie jak większość uproszczonych abstrakcji, wiąże się z overhead( pomyśl o tym jako o ukrytym koszcie), i dobrze jest mieć tego świadomość, ale surowa wydajność prawdopodobnie nie jest najwyższym celem przy użyciu takich konstrukcji i tak.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-11 11:59:45
Właściwie
{
@synchronized(self) {
return [[myString retain] autorelease];
}
}
Przekształca się bezpośrednio w:
// needs #import <objc/objc-sync.h>
{
objc_sync_enter(self)
id retVal = [[myString retain] autorelease];
objc_sync_exit(self);
return retVal;
}
To API dostępne od iOS 2.0 i importowane za pomocą...
#import <objc/objc-sync.h>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-26 19:57:52
Implementacja @synchronized firmy Apple jest open source i można ją znaleźć Tutaj . Mike ash napisał dwa bardzo ciekawe posty na ten temat:
W skrócie zawiera 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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-09 09:37:37
Po prostu kojarzy SEMAFOR z każdym obiektem i używa go.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-31 23:37:04