美文网首页
异步变同步,信号量的简单应用

异步变同步,信号量的简单应用

作者: Boothlee | 来源:发表于2018-09-30 10:17 被阅读39次

最近做一些设备指纹的收集工作,使用到信号量,是为了解决异步API同步使用的问题。先来看需求:

陀螺仪加速计的数据收集,主要有两种方法,一种是pull方法,如下:

- (CMRotationRate)getGyroData
{
    CMRotationRate data;
    data.x = 0.f;
    data.y = 0.f;
    data.z = 0.f;
    if ([self isGyroAvailable] && ![self isGyroActive]){//判断陀螺仪是否可用,是否活跃
        self.gyroUpdateInterval = 0.01;
        [self startGyroUpdates];//开始更新陀螺仪数据
    }
    if ([self isGyroAvailable]){
        data = self.gyroData.rotationRate;//获取到陀螺仪数据
        NSLog(@"X = %.04f",data.x);
        NSLog(@"Y = %.04f",data.y);
        NSLog(@"Z = %.04f",data.z);
        return data;
    }else{
        NSAssert(!(data.x || data.y || data.z), @"陀螺仪未启动或者不可用,数据获取失败");
        return data;
    }
}

但是发现,第一次获取的数据总是0。需要多次调用(一段时间间隔,很小很小)之后才可以获取到数据,这样就造成了一个问题,我只想要调用方法就返回陀螺仪数据,但是你给我返回0.0000 WTF😂

那么,再来看陀螺仪的push方法:

 - (void)startGyroUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMGyroHandler)handler API_UNAVAILABLE(tvos);

Discussion 是这样写的

Starts gyro updates, providing data to
the given handler through the given queue.


开始更新陀螺仪数据,通过block在陀螺仪数据更新后回调返回数据。

如此,真正的需求出来了,如何在block回调之后,return数据呢?归类起来这是一个异步block变同步方法返回的需求,终于,主角信号量要出现了!

先看GCD中的信号量API,非常简单,只有三个方法

[图片上传失败...(image-a87808-1538273800178)]

主要方法:

  • 1.dispatch_semaphore_create //创建一个信号量semaphore
  • 2.dispatch_semaphore_wait //信号量等待
  • 3.dispatch_semaphore_signal //发送一个信号

信号量使用也很简单:

  • 信号量在创建的时候需要传入一个long型value,内部会保存这个value作为初始value,value 做加减变化后,还会保存一份当前的 value。
  • 信号的 wait 和 signal 是互逆的两个操作。signal 会将 value 加一。如果 value 大于 0,wait将 value 减一;此时如果 value 小于零就一直等待。
  • 初始 value 必须大于等于 0,如果为 0 并随后调用 wait 方法,线程将被阻塞直到别的线程调用了 signal 方法。

简单了解了信号量的使用,异步block 同步返回的需求就很好解决了,结合信号量,实现代码如下

- (CMRotationRate)syncGetGyroData
{
    __block CMRotationRate data;//保存block数据
    data.x = 0.f;
    data.y = 0.f;
    data.z = 0.f;
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);//创建信号量传入 0,此时遇如果wait会阻塞线程
    [self startGyroUpdatesToQueue:[[NSOperationQueue alloc] init] withHandler:^(CMGyroData * _Nullable gyroData, NSError * _Nullable error) {
        data = gyroData.rotationRate;
        NSLog(@"X = %.04f",gyroData.rotationRate.x);
        NSLog(@"Y = %.04f",gyroData.rotationRate.y);
        NSLog(@"Z = %.04f",gyroData.rotationRate.z);
        dispatch_semaphore_signal(sema);// 信号量 value 加一
    }];

    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);//信号量为0时会阻塞线程,等待signle
    return data;
}

以上就完美的解决了异步block同步返回的问题。信号量使用起来很简单。
但是需要注意
block回调的线程,如果和syncGetGyroData方法的执行线程相同的话,会造成线程死锁,这里block回调不在主线程,所以可以这样处理,也算是一种小技巧.
另外同样的需求,也可以借助GCD dispatch_group实现:

- (CMRotationRate)syncGetGyroDataByGroup
{
    __block CMRotationRate data;//保存block数据
    data.x = 0.f;
    data.y = 0.f;
    data.z = 0.f;
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    [self startGyroUpdatesToQueue:[[NSOperationQueue alloc] init] withHandler:^(CMGyroData * _Nullable gyroData, NSError * _Nullable error) {
        data = gyroData.rotationRate;
        NSLog(@"X = %.04f",gyroData.rotationRate.x);
        NSLog(@"Y = %.04f",gyroData.rotationRate.y);
        NSLog(@"Z = %.04f",gyroData.rotationRate.z);
        dispatch_group_leave(group);
    }];
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    return data;
}

信号量还可以用于控制线程并发数量,这里就不做详细介绍了,可以参考
https://www.cnblogs.com/yajunLi/p/6274282.html

总结:

这次需求,使用到了信号量。知其然不知其所以然,对于信号量的实现,还不是很清楚。工作中接触新东西,很多情况都是这个过程。所以下一步打算仔细了解一下信号量,GCD源码,我来了!

相关文章

  • 异步变同步,信号量的简单应用

    最近做一些设备指纹的收集工作,使用到信号量,是为了解决异步API同步使用的问题。先来看需求:陀螺仪加速计的数据收集...

  • 信号量

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

  • 多线程的运用

    同步串行队列 同步并发队列 异步串行队列 异步并发队列 队列组 栅栏 队列组和栅栏的组合 信号量 死锁主线程 分析...

  • gennerator 函数

    模拟异步变同步

  • BIO NIO AIO

    同步、异步、阻塞、非阻塞的区别 同步、异步 同步、异步主要是指应用程序和操作系统之间的交互方式。应用程序通过系统调...

  • 网络异步请求同步、顺序处理

    一、异步网络请求按顺序请求(信号量) 打印结果 二、多个网络异步请求最后同步(Group) 打印结果 三、多个网络...

  • 2018-02-26

    iOSGCD同步异步、并发串行栅栏信号量group锁RunLoopAFN 包活定时器Runtimeisaswizz...

  • GCD的同步异步串行并行、NSOperation和NSOpera

    (1)GCD实现的同步异步、串行并行。 ——同步sync应用场景:用户登录,利用阻塞 ——串行异步应用场景:下载等...

  • GCD 信号量 dispatch_semaphore

    Dispatch Semaphore信号量是一种持有计数的信号,实际开发中主要用于保持线程同步,将异步任务转为同步...

  • GCD实现多个异步网络请求效果

    1、使用dispatch_semaphore_t实现多个异步网络请求同步效果(信号量来控制) 1.1dispa...

网友评论

      本文标题:异步变同步,信号量的简单应用

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