[objective-c] Objective-C에서 @synchronized 잠금 / 잠금 해제 방법은 무엇입니까?

@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>


답변

@synchronized의 Apple 구현은 오픈 소스이며 여기 에서 찾을 수 있습니다 . Mike ash는이 주제에 대해 두 가지 흥미로운 게시물을 썼습니다.

간단히 말해서 메모리 포인터를 메모리 주소를 키로 사용하여 객체 포인터를 pthread_mutex_t잠금에 매핑하는 테이블이 있으며 필요에 따라 잠금 및 잠금 해제됩니다.


답변

그것은 단지 세마포어를 모든 객체와 연관시키고 그것을 사용합니다.


답변