关于信号量的文章有很多,但是遇到的这两个问题,也算是采坑了吧~记录一下。
image.png
要做一个关于不断进入直播间的这样一个需求。
需求是要求每个进入直播间的人都要展示进入直播间的动画。
围绕着如何卡住这个后面的人,我想起了信号量这个东西。
dispatch_semaphore_t _setBottom_globalInstancesLock;
dispatch_semaphore_t _darts_globalInstancesLock;
//执行QUEUE的Name
char * SETBOTTOM_QUEUE_NAME = "com.SetBottom_Semaphore.queue";
static void _AlertViewInitGlobal() {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_setBottom_globalInstancesLock = dispatch_semaphore_create(1);
});
}
@implementation Aobject
+(void)initialize{
[super initialize];
_AlertViewInitGlobal();
}
+ (void)showWithMessageType:(ZLRTCMsgSemaphoreType)type showBlock:(void(^)(void))showBlock
{
if (type == ZLRTCMsgSemaphoreType_SetBottom) {
//位于非主线程 不阻塞
dispatch_async(dispatch_queue_create(SETBOTTOM_QUEUE_NAME, DISPATCH_QUEUE_SERIAL), ^{
//Lock
dispatch_semaphore_wait(_setBottom_globalInstancesLock, DISPATCH_TIME_FOREVER);
//保证主线程UI操作
dispatch_async(dispatch_get_main_queue(), ^{
// [[[UIApplication sharedApplication] keyWindow] addSubview:self];
showBlock();
});
});
}
}
+ (void)dismissWithMessageType:(ZLRTCMsgSemaphoreType)type dismissBlock:(void(^)(void))dismissBlock
{
if (type == ZLRTCMsgSemaphoreType_SetBottom) {
dispatch_async(dispatch_queue_create(SETBOTTOM_QUEUE_NAME, DISPATCH_QUEUE_SERIAL), ^{
//Release Lock
dispatch_semaphore_signal(_setBottom_globalInstancesLock);
dispatch_async(dispatch_get_main_queue(), ^{
dismissBlock();
});
});
}
}
创建一个异步串行队列,这样在一个新的队列中去处理这个卡住后面进来的人,从而实现按顺序执行的问题。想法很美好,但现实很骨感。
第一个问题。
刚开始把信号量作为私有变量放到消息互动区。
这样就会出现在切换下个直播间,当前消息互动区被释放掉的时候,还处于wait状态,导致崩溃问题。原本以为在dealloc的时候,发送signal可以解决这个问题,实际上还是会崩溃。
第二个问题。
在上面我把信号量放到消息互动区的对象上,不能实现需求之后,我又想到能否放到单例中,来实现这个问题。
刚开始确实没有问题,但当直播间人数突然激增,或者是直播半小时以上,人数不断累积到6000+的时候,就会发生卡主主线程,只能听到声音的情况。
通过检测内存发现,在卡主之前,内存很平稳,不断wait不断signal,相互配合很好。
但一段时间之后,卡主主线程,那么内存就在不断的增大中。
经过压力测试,如果一秒钟发送几千条消息,那么信号量就会一直卡主,从而卡主主线程。
这算是一个坑吧。希望看到这个文章的人可以避免这个坑。
说一下最后问题的解决,我觉得这个需求,最好简单点直接拿计时器来做,不断从数组中取,时间间隔为动画的时间长度。
网友评论