信号量的使用

作者: coderhlt | 来源:发表于2018-02-06 18:32 被阅读14次

一、信号量的介绍

https://www.jianshu.com/p/24ffa819379c
https://www.jianshu.com/p/56c4838aa3e0

二、信号量的使用

  • 1、使用场景一:首先通过网络请求一获取用户useid,之后用userid为参数发起网络请求二。
#pragma mark - 网络请求一
- (void)getuserId:(dispatch_semaphore_t)semaphore{
   AFHTTPSessionManager *sessionmanger=[[AFHTTPSessionManager alloc]init];
   sessionmanger.responseSerializer=[AFHTTPResponseSerializer serializer];
   [sessionmanger POST:@"https://www.baidu.com/" parameters:nil constructingBodyWithBlock:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
         NSLog(@"请求成功1%@", [NSThread currentThread]);
        useid=@"1234";
       dispatch_semaphore_signal(semaphore);
   } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
       NSLog(@"%@",error);
        dispatch_semaphore_signal(semaphore);
   }];
   
}

#pragma mark - 网络请求二
- (void)requestwithuserid:(NSString *)userid{
   NSDictionary *parms=[NSMutableDictionary dictionary];
   [parms setValue:userid forKey:@"userid"];
   AFHTTPSessionManager *sessionmanger=[[AFHTTPSessionManager alloc]init];
   sessionmanger.responseSerializer=[AFHTTPResponseSerializer serializer];
   [sessionmanger POST:@"https://www.baidu.com/" parameters:userid constructingBodyWithBlock:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
       NSLog(@"请求成功2");
   } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
       NSLog(@"%@",error);
   }];
}

#pragma mark - 使用信号量实现
- (void)viewDidLoad {
    [super viewDidLoad];
    dispatch_semaphore_t semaphore= dispatch_semaphore_create(0); // 创建信号量
    [self getuserId:semaphore];//获取用户useid
 
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//当前信号量为0,一直等待阻塞线程
    [self requestwithuserid:useid];
}

command+R运行一下,没有任何反应。
原因分析:线程卡住了。代码执行到dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER)因为信号量为0,当前线程会被阻塞。而当前线程是主线程,网络请求一成功后回调到主线程,因为主线程被阻塞 造成信号量无法释放,一直卡住。
解决方案就是开启一个异步的线程

- (void)viewDidLoad {
    [super viewDidLoad];
    //创建一个并行队列
    dispatch_queue_t queque = dispatch_queue_create("GoyakodCreated", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queque, ^{
        dispatch_semaphore_t semaphore= dispatch_semaphore_create(0); // 创建信号量
        [self getuserId:semaphore];
        dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
        [self requestwithuserid:useid];
    });
}
  • 2、使用场景二:从客户端有顺序的一张张上传图片
    dispatch_queue_t queque = dispatch_queue_create("GoyakodCreated", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queque, ^{
        for (NSInteger i=0;i<imageArray.count;i++) {
            dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
            [[AFHttpRequest shareRequest]  unifiedPicConversionWithchannelNo:@"" businessNum:@"" serialNum:serialNum sendType:@"" picName:picName picDirection:@"" picIoStr:picBase64Str serverSuccessFn:^(id dict) {
                dispatch_semaphore_signal(semaphore);
            } serverFailureFn:^(NSError *error) {
                dispatch_semaphore_signal(semaphore);
      
            }];
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        }
    });
  • 3、使用场景三:控制线程并发数
//定义一个信号量,初始化为10
dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
    
//同时执行100个任务
 for (int i = 0; i < 100; i++)
 {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
    //当前信号量-1
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
    NSLog(@"任务%d执行",i+1);
            
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:kUrlString]];

    dispatch_async(dispatch_get_main_queue(), ^{
        //TODO:刷新界面
    });
            
    //当前信号量+1
    dispatch_semaphore_signal(semaphore);
            
    });
}

开始初始化一个信号量,默认为10,然后同时执行100个任务,所以每次最大并发是10。dispatch_semaphore_wait表示是当前的信号量减去1,因为已经启动一个任务,所以通过这个方法来修改信号量的值。同样,当当前任务执行完后,要释放信号量,使当前信号量加1,所以用dispatch_semaphore_signal方法

  • 4、使用场景四:多个网络请求后刷新UI
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    dispatch_group_t group = dispatch_group_create();
    // 创建信号量
   semaphore = dispatch_semaphore_create(0);
    // 创建全局并行
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_group_async(group, queue, ^{

        [self request1];

    });
    
    dispatch_group_async(group, queue, ^{
       
        [self request2];
 
    });
    
    dispatch_group_notify(group, queue, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        //在这里 进行请求后的方法,回到主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            
            NSLog(@"更新UI");
            
        });
    });
    NSLog(@"12344");
    
}
- (void)request1{
    AFHTTPSessionManager *manger=[[AFHTTPSessionManager alloc]init];
    manger.responseSerializer=[AFHTTPResponseSerializer serializer];
    [manger POST:@"https://www.baidu.com" parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"请求成功1");
        dispatch_semaphore_signal(semaphore);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
         dispatch_semaphore_signal(semaphore);
    }];

}
- (void)request2{
    AFHTTPSessionManager *manger=[[AFHTTPSessionManager alloc]init];
    manger.responseSerializer=[AFHTTPResponseSerializer serializer];
    [manger POST:@"https://www.baidu.com" parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"请求成功2");
        dispatch_semaphore_signal(semaphore);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
         dispatch_semaphore_signal(semaphore);
    }];
   
}

或者这样

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    dispatch_group_t group = dispatch_group_create();
   
    // 创建全局并行
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_group_async(group, queue, ^{

        [self request1];

    });
    
    dispatch_group_async(group, queue, ^{
       
        [self request2];
 
    });
    
    dispatch_group_notify(group, queue, ^{

        //在这里 进行请求后的方法,回到主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            
            NSLog(@"更新UI");
            
        });
    });
    NSLog(@"12344");
    
}
- (void)request1{
    // 创建信号量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    AFHTTPSessionManager *manger=[[AFHTTPSessionManager alloc]init];
    manger.responseSerializer=[AFHTTPResponseSerializer serializer];
    [manger POST:@"https://www.baidu.com" parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"请求成功1");
         NSLog(@"%ld", dispatch_semaphore_signal(semaphore));
       ;
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
         dispatch_semaphore_signal(semaphore);
        NSLog(@"%@",semaphore);
    }];
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
- (void)request2{
    // 创建信号量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    AFHTTPSessionManager *manger=[[AFHTTPSessionManager alloc]init];
    manger.responseSerializer=[AFHTTPResponseSerializer serializer];
    [manger POST:@"https://www.baidu.com" parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"请求成功2");
        dispatch_semaphore_signal(semaphore);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
         dispatch_semaphore_signal(semaphore);
    }];
     dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
@end

相关文章

  • iOS进阶-GCD信号量-dispatch_semaphore_

    目录 GCD信号量概念 使用API 实例使用 GCD信号量概念 使用API : dispatch_semaphor...

  • iOS底层--GCD应用

    手动目录GCD简介信号量信号量的理解信号量的使用信号量的代码实操信号量阻塞哪里的任务?栅栏函数dispatch_b...

  • [java并发编程]基于信号量semaphore实现限流器

    [TOC] 一、什么是信号量 “信号量”在编程术语中使用单词semaphore,那什么是“信号量”?信号量就好比你...

  • java concurrency <信号量>

    java concurrency <信号量> 使用信号量的目的 线程信号量的目的是使线程能够彼此发送信号。 此外,...

  • 信号量

    信号量的使用: 信号量使用的业务场景: 一、锁 YYKit加锁代码: 二、异步返回 三、控制并发量,降低性能。

  • 信号量实现网络顺序执行

    信号量的方式实现 CODE CODE ANALYSIS 使用信号量需要注意,dispatch_semaphore_...

  • Java中的管程模型

    操作系统使用信号量解决并发问题,Java选择使用管程(Monitor)解决并发问题。信号量和管程是等价的,可以使用...

  • 信号量

    信号量的使用,其实就是把异步变同步,信号量=0时等待执行,执行完之后把信号量+1,当信号量>0时就可以顺序执行了。...

  • iOS多线程异步信号量

    使用GCD信号量写了一个小demo,在不使用调度组和线程依赖的情况下,可以使用信号量git链接: https://...

  • GCD信号量使用

    1.信号量使用 信号量:就是一种可用来控制访问资源的数量的标识,设定了一个信号量,在线程访问之前,加上信号量的处理...

网友评论

    本文标题:信号量的使用

    本文链接:https://www.haomeiwen.com/subject/mrgwzxtx.html