>

내 코드는 다음과 같습니다 :

- (void)viewDidLoad {
    [super viewDidLoad];
    [self testGCD];
}
- (void)testGCD {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"1");
        return;
    });
    NSLog(@"2");
}

콘솔 12를 인쇄했습니다.

원하는 것은 처음 1 만 인쇄하는 것입니다. 아마도 return 생각  메소드에서 반환되지 않고 대신 블록에서 반환됩니다.

이 GCD 블록의 현재 메소드에서 리턴 할 수있는 방법이 있습니까?


  • 답변 # 1

    dispatch_once 정의를 보면  그런 다음 그들이 DISPATCH_EXPECT 를 사용하고 있음을 알 수 있습니다.   onceToken 를 비교하기 위해 . if (onceToken != -1) 를 사용할 수도 있습니다  그러나 DISPATCH_EXPECT  컴파일러에게 onceToken == -1 의 확률을 알려 코드를 최적화합니다  훨씬 더 높습니다. 이를지점 예측

    이라고합니다.
    - (void)testGCD {
      static dispatch_once_t onceToken;
      if (DISPATCH_EXPECT(onceToken, ~0l) != ~0l) {
        dispatch_once(&onceToken, ^{
          NSLog(@"1");
          return;
        });
      }
      else {
        NSLog(@"2");
      }
    }
    
    

  • 답변 # 2

    블록을 사용하여 문제를 해결하십시오.

    - (void)testGCD {
        __block void(^codeBlock)(void) = ^{ NSLog(@"2"); };
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            codeBlock = ^{ NSLog(@"1"); };
        });
        codeBlock();
    }
    
    

  • 답변 # 3

    - (void)testGCD {
        static dispatch_once_t onceToken;
        __block NSString *text = @"2";
        dispatch_once(&onceToken, ^{
            text = @"1";
        });
        NSLog(@"%@", text);
    }
    
    

  • 답변 # 4

    와이즈 비즈  statement는 현재 엔 클로징 범위에서 반환하며, 귀하의 경우에는 블록입니다. 외부 둘러싸는 범위에서 돌아올 수 없습니다.

    간단한 부울 플래그를 사용하여 코드가 스레드 실행에 안전한지 확인하기 위해 직렬 디스패치 큐와 함께 코드가 처음으로 실행되었는지 여부를 확인할 수 있습니다.

    같은 것 :

    return
    
    

    직렬 디스패치 큐를 사용하면 - (void)testGCD { static dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", NULL); static bool firstRun = YES; dispatch_sync(queue, ^{ if (firstRun) { NSLog(@"1); firstRun = NO; } else { NSLog(@"2"); } }); } 를 동시에 업데이트 할 수 없습니다.

  • 답변 # 5

    블록은 완전히 분리 된 방법과 같습니다. 와이즈 비즈  블록에서만 반환됩니다. 효과적으로 필요한 것 :

    firstRun
    
    

    귀하의 경우 간단한 자물쇠를 사용하려고 시도 할 수 있지만이 경우 얼마나 안전한지 확실하지 않습니다.

    return
    
    

    그러나 여전히 멀티 스레딩시 결과가 불안정 할 수 있습니다. 결과가 정확하려면 이것을 원자 적으로 실행해야 할 수도 있습니다. 잠재적 인 문제는 다음과 같습니다.

    나사 A와 스레드 B가 동일한 방법을 실행하기 시작합니다.

    스레드 A가 토큰을 수집하고 - (void)testGCD { static BOOL didTrigger = NO; if(didTrigger) { NSLog(@"2"); } else { didTrigger = YES; NSLog(@"1"); } } 를 잠금 해제합니다

    나사 B는 블록을 건너 뛰고 - (void)testGCD { static dispatch_once_t onceToken; static BOOL didInvokeOnceBlock = NO; static BOOL didPassSkippedBlock = NO; dispatch_once(&onceToken, ^{ NSLog(@"1"); didInvokeOnceBlock = YES; }); if(didInvokeOnceBlock && didPassSkippedBlock) { NSLog(@"2"); } didPassSkippedBlock = YES; } 를 잠금 해제합니다  그러나 didInvokeOnceBlock 를 건너 뜁니다

    스레드 A가 didPassSkippedBlock 를 불러옵니다

    NSLog(@"2");

관련 자료

  • 이전 Swift3 iOS의 UITextField에는 숫자 및 점 문자 만 허용되어야합니다
  • 다음 excel - 셀의 값을 기반으로 매크로를 실행하는 방법은 무엇입니까?