需求:异步操作,比如网络请求,要求异步回调后拿到这个值,然后返回这个值

需求分析:实际上这个应用场景是著名网络请求框架AFNNetworking一个

- (NSString *)httpNet{
    
    // 1.创建信号量
    //传入的参数为long 参数value必须大于或等于0,一般情况都是传0
    dispatch_semaphore_t signal = dispatch_semaphore_create(0.0);

    __block NSString *objectID;

    // 模拟block异步
    dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        // 异步的耗时操作,比如:睡眠3秒
        [NSThread sleepForTimeInterval:3];
        objectID = @"222";
        NSLog(@"objectID=%@",objectID);
        // 2.发送信号量
        // 这个函数会使传入的信号量dsema的值加1
        dispatch_semaphore_signal(signal);
    });
    // 这个函数的作用是这样的,如果dsema信号量的值大于0,该函数所处线程就继续执行下面的语句,并且将信号量的值减1
    // 这个函数会使传入的信号量dsema的值减1;
    // 如果desema的值为0,那么这个函数就阻塞当前线程等待timeout
    
    // 关键点:如果想阻塞线程,那么所传的参数signal值必须为0,异步回调成功后,想要取消阻塞线程,需要信号量dsema的值加1,那么就会自动跳转到`dispatch_semaphore_wait`这行代码执行,这行代码会使信号量dsema的值减1;
    
    // 3.等待信号量
    dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER);
    // 如果等待期间没有获取到信号量或者信号量的值一直为0,那么等到timeout时,其所处线程自动执行其后语句
    NSLog(@"objectID=%@",objectID);
    return objectID;
}

步骤

总结: 通常等待信号量和发送信号量的函数是成对出现的,在异步线程中使用 解决问题:并发队列中的任务同步执行的要求/用信号量机制使异步线程完成同步操作

面试题:AFNetWorking与dispatch_semaphore_t能共存吗?如图

demo

发生了死锁 原因: AFN框架已经把successfailure的回调放在了主线程中. 所以程序在走到dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOEVER)这句代码的时候, 已经将主线程锁住了, 所以同处于主线程的successfailure的回调block压根就不会走, 所以同时放在主线程中的dispatch_semaphore_signal(semaphore)同样也不会走, 那么信号量的 value值也不可能增大, 所以value值一直为0, 那么被锁住的主线程就永远锁住了