1

나는 다른 managedObjectContext.parent을 설정하는 경우를 제외하고 NSMainQueueConcurrencyType나는이 교착 상태를 어떻게 해결합니까?

+ (NSManagedObjectContext *)managedObjectContextMainThread 
{ 
    static NSManagedObjectContext *__managedObjectContext=nil; 
    @synchronized(self) 
    { 
     if (__managedObjectContext != nil) 
     { 

     } 
     else { 
      NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
      if (coordinator != nil) 
      { 
       __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
       [__managedObjectContext setPersistentStoreCoordinator:coordinator]; 
      } 
     } 
    } 
    return __managedObjectContext; 
} 

주요 managedObjectContext 주 스레드의 외부 액세스되지 않습니다의 concurency 유형 하나 managedObjectContext 있습니다. 따라서 mainManagedObjectContext는 모든 스레드의 부모입니다.

이제 프로그램을 실행하면 때로는 교착 상태에 빠집니다. 나는 프로그램을 일시 중지하고이 내가 볼 것입니다 :

enter image description here

우리가 그림에서 볼 때, 교착 상태에있는 것 같다 2 개 스레드가 있습니다. 첫 번째는 주 스레드입니다.

@synchronize (자체)에서 교착 상태가 발생합니다. 합리적인.

enter image description here

그래서 잠금을 __managedObjectContext을 보유하고있는 정적 변수의 영구 저장소를 변경하려고 할 때 :

다른 스레드에서 교착 상태입니다.

나를 반복 다시 코드를 넣어 보자 : 땅에 그렇지 않으면 [__managedObjectContext setPersistentStoreCoordinator:coordinator];

아무것도가 __managedObjectContext에 접근하지 왜

+ (NSManagedObjectContext *)managedObjectContextMainThread 
{ 
    static NSManagedObjectContext *__managedObjectContext=nil; 
    @synchronized(self) //Main thread deadlock here 
    { 
     if (__managedObjectContext != nil) 
     { 

     } 
     else { 
      NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
      if (coordinator != nil) 
      { 
       __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
       [__managedObjectContext setPersistentStoreCoordinator:coordinator]; //Secondary thread dead lock here 
      } 
     } 
    } 
    return __managedObjectContext; 
} 

내 질문입니다. 두 번째 스레드 (기본이 아닌 스레드)가 __managedObjectContext를 부모 컨텍스트로 설정하려고합니다. 첫 번째 스레드는 @synchronized에서 행복하게 기다리고 있습니다. 아무것도하지 않습니다.

왜 교착 상태가되고 어떻게 해결할 수 있습니까?

아, 여기 작성 managedObjectContext 아이 :

@synchronized(self) 
{ 
    if ([managedObjectContexts objectForKey:[self threadKey]] == nil) { 
     NSManagedObjectContext *threadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
     threadContext.parentContext = [self managedObjectContextMainThread]; //Stuck here. This goes straight to above function managedObjectContextMainThread where it stucks. 
     threadContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; 
     [managedObjectContexts setObject:threadContext forKey:[self threadKey]]; 
    } 
} 

답변

2

문제는 내가 메인 스레드가 아닌 다른 스레드에서 주요 관리 개체 컨텍스트를 만들려고합니다.

어떤 이유로 작동하지 않습니다.

나는 여전히 게으른로드를 좋아합니다. 그래서 오직 할 필요가있는 다른 managedObjectContexts가 생성되기 전에 주요 managedObjectContext가

  1. 메인 스레드
  2. 에 생성되어 있는지 확인하는 것입니다.
  3. 나는 내 프로그램 dispatch_sync에 대한 작업처럼

은 그래서 보이는 먼저 다른 managedObjectContexts에 액세스하려고하지 않도록하고 싶지 않아요. 나는 모든 배경 자식 managedObjectContexts을 만들기 전에

dispatch_sync(dispatch_get_main_queue(),^{ 
     [self managedObjectContextMainThread];//Access it once to make sure it's there 
    }); 

:

나는 다음이 코드를 추가했습니다.일단 생성 된 함수는 정적 변수 만 반환하기 때문에 빠릅니다.

+(NSManagedObjectContext *)managedObjectContext { 


    NSThread *thread = [NSThread currentThread]; 
    //BadgerNewAppDelegate *delegate = [BNUtilitiesQuick appDelegate]; 
    //NSManagedObjectContext *moc = delegate.managedObjectContext; 

    if ([thread isMainThread]) { 
     //NSManagedObjectContext *moc = [self managedObjectContextMainThread]; 
     return [self managedObjectContextMainThread]; 
    } 
    else{ 
     dispatch_sync(dispatch_get_main_queue(),^{ 
      [self managedObjectContextMainThread];//Access it once to make sure it's there 
     }); 
    } 

    // a key to cache the context for the given thread 
    NSMutableDictionary *managedObjectContexts =[self thread].managedObjectContexts; 

    @synchronized(self) 
    { 
     if ([managedObjectContexts objectForKey:[self threadKey]] == nil) { 
      NSManagedObjectContext *threadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
      threadContext.parentContext = [self managedObjectContextMainThread]; 
      //threadContext.persistentStoreCoordinator= [self persistentStoreCoordinator]; //moc.persistentStoreCoordinator;// [moc persistentStoreCoordinator]; 
      threadContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; 
      [managedObjectContexts setObject:threadContext forKey:[self threadKey]]; 
     } 
    } 


    return [managedObjectContexts objectForKey:[self threadKey]]; 
} 
+2

간단한 설명 : 관리 객체 컨텍스트를 만드는 것은 매우 저렴한 작업입니다. 정말입니다! 따라서 게으른 문맥 작성은 실제로 필요하지 않으며 추가 복잡성, 글쓰기에 더 많은 코드를 추가하고 더 많거나 적은 것을 얻을 수 있습니다. 게으른 생성/로딩은 실제로 의미가있는 경우에만 적용해야합니다. 컨텍스트를 느리게 생성하는 이유는 무엇입니까? 문자열, 숫자, 작은 배열은 모두 느리게 생성 될 수 있지만 간단하게 유지하기 위해 수행되지는 않습니다. –

관련 문제