iOS 스레드 잠금 사고

3815 단어
  dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"2");
    });
  NSLog(@"3");


상기 코드가 잠겨 죽는 원인에 대해 몇 가지 개념을 정리해야 한다.Queue와 Async, Sync.Queue는 직렬로 나뉘어 있고, 병렬로 나뉘어 있으며, 이름만 보고 뜻을 알 수 있다.Async: 비동기 실행, dispatch 사용async에서 Block을 호출합니다. 이 Block은 지정한queue 팀 끝에 놓여서 실행을 기다리지만 디스패치async가 곧 돌아올 겁니다.Sync:동기화, dispatch 사용sync에서 Block을 호출합니다. 이 Block은 지정한queue 팀 끝에 놓여서 실행을 기다리고, sync 함수가 돌아올 때까지 현재queue를 막습니다.
name은 상술한 문제에 대해 이해하기 쉽습니다. 현재 대기열은Main 입니다.queue, 동시에 지정한 대기열도mainqueue.Block 추가mainqueue 대열의 끝에서 실행됩니다. 그러나 이것은 동기화 직렬 대기열이기 때문에 현재 라인을 막습니다. 그러면 Block 작업을 실행할 수 없고sync 함수도 되돌릴 수 없습니다. 또한 라인이 막히고 잠겨 죽습니다.
dispatch_queue_t queue = dispatch_queue_create("abc",             
    DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
        NSLog(@"%@", [NSThread currentThread]);
 });
 NSLog(@"1");

여기도 같은 동기화 직렬 대기열인데 왜 자물쇠가 사라지지 않았을까요?막힌 대기열과 지정한 대기열이 같은 대기열이 아니기 때문에
NSLog(@"1"); //   1
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    NSLog(@"2"); //   2
});
NSLog(@"3"); //   3

//   1、2、3

우선 작업 1을 실행하고 동기화 라인을 만나면 프로그램이 대기에 들어갑니다.퀘스트 2가 완성될 때까지 기다려야 퀘스트 3을 계속 수행할 수 있습니다.dispatchget_global_queue에서 알 수 있듯이 작업 2는 전역의 병렬 대기열에 추가되었습니다. 병렬 대기열이 작업 2를 수행한 후에 홈 대기열로 돌아가서 작업 3을 계속 수행합니다.
dispatch_queue_t queue = dispatch_queue_create("com.demo.serialQueue", DISPATCH_QUEUE_SERIAL);
NSLog(@"1"); //   1
dispatch_async(queue, ^{
    NSLog(@"2"); //   2
    dispatch_sync(queue, ^{  
        NSLog(@"3"); //   3
    });
    NSLog(@"4"); //   4
});
NSLog(@"5"); //   5

//  :1、2、5 (2,5     )

이 사례는 시스템이 제공하는 직렬이나 병렬 대기열을 사용하지 않고 디스패치를 통해queue_create 함수는 DISPATCH 를 생성합니다.QUEUE_SERIAL의 직렬 큐입니다.
임무 수행 1;비동기 스레드를 만나면 [퀘스트 2, 동기 스레드, 퀘스트 4]를 직렬 대기열에 추가합니다.비동기 스레드이기 때문에 주 스레드의 작업 5는 비동기 스레드의 모든 작업이 완성되기를 기다릴 필요가 없습니다.퀘스트 5는 기다릴 필요가 없기 때문에 2와 5의 출력 순서는 확정할 수 없습니다.퀘스트 2가 실행된 후 동기화 라인을 만났을 때 퀘스트 3을 직렬 대기열에 추가합니다.또한 작업 4가 작업 3보다 먼저 직렬 대기열에 가입하기 때문에 작업 3은 작업 4가 완성된 후에야 실행할 수 있습니다.그러나 퀘스트 3이 있는 동기화 라인이 막히기 때문에 퀘스트 4는 퀘스트 3이 실행된 후에 실행해야 합니다.이로 인해 또 무한한 기다림에 빠져 사라진 자물쇠를 만들었다.
 dispatch_async(dispatch_get_global_queue(0, 0), ^{
         NSLog(@"1"); //   1
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"2"); //   2
        });
        NSLog(@"3"); //   3
 });
NSLog(@"4"); //   4
while (1) {
}
NSLog(@"5");//  5

//  1、4,     

위의 몇 가지 사례의 분석과 유사하게 먼저 어떤 임무가 Main Queue에 추가되었는지 살펴보자. [비동기적인 라인, 임무 4, 사순환, 임무 5].Global Queue 비동기 스레드에 가입하는 작업은 다음과 같습니다. [퀘스트 1, 동기 스레드, 퀘스트 3].
첫 번째는 비동기 라인입니다. 퀘스트 4는 기다릴 필요가 없기 때문에 결과 퀘스트 1과 퀘스트 4의 순서가 일정하지 않습니다.작업 4가 완료되면 프로그램이 데드사이클에 들어가고 Main Queue가 차단됩니다.그러나 Global Queue에 추가된 비동기 스레드는 영향을 받지 않고 작업 1 뒤에 있는 동기 스레드를 계속 수행합니다.
동기화 스레드에서 작업 2를 주 스레드에 추가하고 작업 3은 작업 2가 완성된 후에야 실행할 수 있습니다.이때의 주선은 이미 사순환에 의해 막혔다.그래서 퀘스트 2는 실행할 수 없습니다. 물론 퀘스트 3도 실행할 수 없고 사순환 후의 퀘스트 5도 실행할 수 없습니다.
결국 1과 4의 순서가 정해지지 않은 결과만 얻을 수 있다
    dispatch_queue_t queue = dispatch_queue_create("cucci", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue2 = dispatch_queue_create("cucco", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
        NSLog(@"111==%@",[NSThread currentThread]);
        dispatch_sync(queue2, ^{
            NSLog(@"222--%@",[NSThread currentThread]);
        });
        NSLog(@"333==%@",[NSThread currentThread]);
    });
    NSLog(@"444==%@",[NSThread currentThread]);
   111,222,333,444;

그래서 기본적으로 이런 결론을 얻을 수 있다. 새로운 라인을 개척했기 때문에 일반적으로 자물쇠가 사라지지 않는다. 자물쇠가 사라지는 것은 동기화 작업과 현재 작업이 같은 대열에 있는지 여부이다. 만약에 기본적으로 자물쇠가 사라지면

좋은 웹페이지 즐겨찾기