6

Objective C에서 다양한 스레드의 NSMutableArray 인스턴스를 사용하고 있으며이를 @synchronized를 사용하여 스레드로부터 안전하게 보호합니다. 현재이 배열에 대한 모든 액세스는 @synchronized 블록, 심지어 objectAtIndex : 메소드로 보호됩니다. 그럼에도 불구하고 어떤 메소드가 실제로 @synchronized로 보호 될 필요가 있는지 궁금합니다. 읽기 액세스를 보호해야합니까?NSMutableArray 컬렉션 및 @Synchronized 블록

'ObjectAtIndex'가 'removeObject'와 동시에 보호되고 호출되지 않으면 어떻게됩니까?

모든 방법이 성능에 대해 @ 동기화 됨으로 보호되는 경우? (필자는 tcp/udp 게임 서버를 작성하고 퍼포먼스를 줄이거 나 자물쇠를 생성하는 경우이 배열을 과보호하지 않으려 고합니다.)

예를 들어 'containsObject :'메서드가 개체를 찾기 위해 열거되고 다른 스레드에서 'removeObject :'에 대한 concurent 호출을 피해야한다고 가정합니다.

아마 좋은 해결책은

도움말 및 제안을 환영합니다 ... 너무 다른 잠금이 (읽기 및 쓰기 권한을)하는 것입니다!

고마워요.

설명하기 위해 아래 예제 코드를 찾아주세요 :

@interface TestClass : NSObject 
{ 
    NSMutableArray * array; 
} 

@end 

@implementation TestClass 

- (id)init 
{ 
    self = [super init]; 
    if (self) 
    { 
     array = [NSMutableArray array]; 
    } 
    return self; 
} 

-(id)objectAtIndex:(NSUInteger)index 
{ 
    @synchronized(array) **// IS IT USEFUL OR NOT ??** 
    { 
     return [array objectAtIndex:index]; 
    } 
} 

-(void)removeObject:(id)object 
{ 
    @synchronized(array) 
    { 
     [array removeObject:object]; 
    } 
} 

-(void)compute 
{ 
    @synchronized(array) 
    { 
     for (id object in array) 
     { 
      [object compute]; 
     } 
    } 
} 

@end 

답변

5

예, 읽기 동기화해야하는 것은 돌연변이와 동시에 일어나는 것을 방지하기 위해 액세스합니다. 읽기 액세스는 다른 읽기 액세스와 동시에 안전하게 실행할 수 있습니다.

독자가 여러 명인 경우 읽기 - 쓰기 잠금 체계를 조사하는 것이 좋습니다. pthread 읽기 - 쓰기 잠금 (예 : pthread_rwlock_...())을 사용할 수 있습니다.

또는 "장벽"루틴으로 OS X 10.7 이상 및 iOS 5 이상에서 GCD를 사용할 수 있습니다. 개인 동시 대기열을 만듭니다. 정상적으로 모든 읽기 작업을 제출하십시오 (예 : dispatch_sync()). dispatch_barrier_async()과 같은 장벽 루틴을 사용하여 돌연변이 작업을 제출하십시오. (돌연변이가 완료되기 전에 완료해야한다는 것을 알 필요가 없기 때문에 비동기적일 수 있습니다. 변이를 제출 한 후에 제출 된 모든 읽기가 돌연변이 결과를 볼 수 있다는 것을 알고 있어야합니다.)

WWDC 2011 session video for Session 210 - Mastering Grand Central Dispatch에 액세스 할 수있는 방법에 대해 자세히 알아볼 수 있습니다.

+0

저는 GCD 솔루션을 정말 좋아합니다. 내가 변하지 않는 배열을 많이 사용하고 있기 때문에 (그리고 사전도) 보호하고 싶습니다. 모든 메소드를 오버라이드하고 배열이나 사전의 각 인스턴스에 대해 dispatch_queue_t를 추가하는 GCDMutableArray와 GCDMutableDictionary를 만들 수 있는지 궁금합니다. 하지만 그것은 자신의 dispatch_queue와 10 변하기 쉬운 사전을 가지고 좋은 해결책입니까? 그리고 각 인스턴스마다 다른 대기열을 만들 수 있습니까? dispatch_queue_create는 이름을 arg로 취하고이 이름을 생성하는 방법은 무엇입니까? 아마도 이런 종류의 보호 된 배열과 사전은 이미 작성되었지만 아무것도 찾을 수 없습니다. –

+0

나는 그런 클래스가 일반적으로 유용하다고 생각하지 않는다. 컨테이너와 같은 하위 수준의 클래스에 집중하여 스레드 안전성을 달성 할 수있는 경우는 거의 없습니다. 클래스의 추상화 수준에서 클래스를 분석해야 할 필요가 거의 있습니다. 클래스의 추상화 단계에서 스레드의 안전성을 구현하는 것뿐만 아니라 인터페이스를 디자인하는 것입니다. 즉, 디스패치 대기열은 저렴하고 Apple은 합리적인 설계가 요구하는만큼 많은 것을 만들 것을 권장합니다. –

0

실제로하고있는 일이 실제로 도움이되지 않는다는 사실을 알고 있어야합니다. 예를 들어 배열에 10 개의 요소가 있고 다른 스레드가 [myObject removeObject : someObject]를 호출하는 동안 [myObject objectAtIndex : 9]를 호출하면 첫 번째 호출이 더 이상 존재하지 않는 배열 요소에 액세스하고 예외가 throw됩니다 .

objectAtIndex는 다른 스레드가 개체를 제거하거나 삽입 할 수있는 경우 실제로 유용하지 않습니다.