@synchronized는 상호 배제를 달성하기 위해 “잠금”및 “잠금 해제”를 사용하지 않습니까? 그러면 어떻게 잠금 / 잠금 해제합니까?
다음 프로그램의 출력은 “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 언어 레벨 동기화는 뮤텍스를 사용합니다 NSLock
. 의미 상 약간의 기술적 차이가 있지만 기본적으로 공통적 인 (보다 원시적 인) 엔티티 위에 구현 된 두 개의 별도 인터페이스로 생각하는 것이 맞습니다.
특히 a NSLock
를 사용하면 명시 적 잠금이있는 반면 @synchronized
동기화하는 데 사용하는 객체와 관련된 암시 적 잠금이 있습니다. 언어 수준 잠금의 이점은 컴파일러가이를 이해하여 범위 지정 문제를 처리 할 수 있지만 기계적으로는 기본적으로 동일하게 동작한다는 것입니다.
@synchronized
컴파일러 재 작성으로 생각할 수 있습니다 .
- (NSString *)myString {
@synchronized(self) {
return [[myString retain] autorelease];
}
}
로 변환됩니다 :
- (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;
}
실제 변환이 더 복잡하고 재귀 잠금을 사용하기 때문에 정확하게 맞지는 않지만 요점을 파악해야합니다.
답변
Objective-C에서 @synchronized
블록은 자동으로 잠금 및 잠금 해제 (및 가능한 예외)를 처리합니다. 런타임은 기본적으로 동기화중인 객체와 연결된 NSRecursiveLock을 동적으로 생성합니다. 이 Apple 설명서 에서 자세히 설명합니다. 이것이 NSLock 서브 클래스에서 로그 메시지를 볼 수없는 이유입니다. 동기화하는 객체는 NSLock뿐만 아니라 무엇이든 될 수 있습니다.
기본적으로 @synchronized (...)
코드를 간소화하는 편리한 구조입니다. 가장 단순화 된 추상화와 마찬가지로 오버 헤드 (숨겨진 비용으로 생각)와 관련이 있으며, 그것을 알고있는 것이 좋지만, 그러한 구조를 사용할 때 원시 성능은 아마도 최고의 목표는 아닙니다.
답변
사실은
{
@synchronized(self) {
return [[myString retain] autorelease];
}
}
다음으로 직접 변환합니다.
// needs #import <objc/objc-sync.h>
{
objc_sync_enter(self)
id retVal = [[myString retain] autorelease];
objc_sync_exit(self);
return retVal;
}
이 API는 iOS 2.0부터 사용할 수 있으며 다음을 사용하여 가져옵니다.
#import <objc/objc-sync.h>