想说说被废弃的dispatch_get_current_queue,不得不提一个概念:可重入。
什么是可重入,来自维基百科:若一个程序或子程序可以“安全的被并行执行(Parallel computing)”,则称其为可重入(reentrant或re-entrant)的。
即当该子程序正在运行时,可以再次进入并执行它(并行执行时,个别的执行结果,都符合设计时的预期)。
若一个函数是可重入的,则该函数:
- 不能含有静态(全局)非常量数据
- 不能返回静态(全局)非常量数据的地址
- 只能处理由调用者提供的数据
- 不能依赖于单实例模式资源的锁
- 不能调用(call)不可重入的函数(有呼叫(call)到的函数需满足前述条件)
有时候我们很希望知道当前执行的queue是谁,比如UI操作需要放在main queue中执行。如果可以知道当前工作的queue是谁,就可以很方便的指定一段代码操作在特定的queue中执行。dispatch_get_current_queue() 正好能帮上忙。于是乎,在指定的queue中做一些操作,就可以非常清晰的实现:
void func(dispatch_queue_t queue, dispatch_block_t block)
{
if (dispatch_get_current_queue() == queue) {
block();
}else{
dispatch_sync(queue, block);
}
}
然后潜意识里,觉得这个函数是可重入的。
但当target queue恰好是current queue时,同步阻塞会导致死锁。
- (void)deadLockFunc
{
dispatch_queue_t queueA = dispatch_queue_create("com.yiyaaixuexi.queueA", NULL);
dispatch_queue_t queueB = dispatch_queue_create("com.yiyaaixuexi.queueB", NULL);
dispatch_sync(queueA, ^{
dispatch_sync(queueB, ^{
dispatch_block_t block = ^{
//do something
};
func(queueA, block);
});
});
}
问题出在GCD队列本身是不可重入的,串行同步队列的层级关系,是出现问题的根本原因。
为了防止类似的误用,苹果在iOS6废弃了dispatch_get_current_queue()方法。强大的dispatch_get_current_queue()也只能当作一个调试工具了。
那么应该如何保证GCD方法可重入呢?
- dispatch_queue_set_specific 标记队列
- 递归锁
分别给出两种方法的示例代码片段:
1)dispatch_queue_set_specific
dispatch_queue_t queueA = dispatch_queue_create("com.yiyaaixuexi.queueA", NULL);
dispatch_queue_t queueB = dispatch_queue_create("com.yiyaaixuexi.queueB", NULL);
dispatch_set_target_queue(queueB, queueA);
static int specificKey;
CFStringRef specificValue = CFSTR("queueA");
dispatch_queue_set_specific(queueA,
&specificKey,
(void*)specificValue,
(dispatch_function_t)CFRelease);
dispatch_sync(queueB, ^{
dispatch_block_t block = ^{
//do something
};
CFStringRef retrievedValue = dispatch_get_specific(&specificKey);
if (retrievedValue) {
block();
} else {
dispatch_sync(queueA, block);
}
});
2)递归锁
void dispatch_reentrant(void (^block)())
{
static NSRecursiveLock *lock = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
lock = [[NSRecursiveLock alloc]init];
});
[lock lock];
block();
[lock unlock];
}
dispatch_queue_t queueA = dispatch_queue_create("com.yiyaaixuexi.queueA", NULL);
dispatch_block_t block = ^{
//do something
};
dispatch_sync(queueA, ^{
dispatch_reentrant(block);
});
分享到:
相关推荐
ios demo,dispatch_async,DISPATCH_QUEUE_CONCURRENT,多任务并发执行,自动创建多线
在将任务插入到queue的时候, dispatch_barrier_sync需要等待自己的任务结束之后才会继续程序,然后插入被写在它后面的任务。 2、dispatch_barrier_async:异步栅栏函数会开辟新线程执行block;ispatch_barrier_...
以上两种方式都是模拟任务block内为异步操作的情况,方式一先执行的dispatch_group_notify里的代码,后执行的dispatch_group_async里的任务代码,这与我们的初衷相违背。如果任务block内为同步操作时,则无论哪种...
ios demo,主队列,异步调度,手动创建线程,detachNewThreadSelector dispatch_get_main_queue
dispatch_queue_t queue = dispatch_queue_create("com.gcd-dispatch_group_async(gro
两种方式都是模拟任务block内为异步操作的情况,方式一先执行的dispatch_group_notify里的代码,后执行的dispatch_group_async里的任务代码,这与我们的初衷相违背。如果任务block内为同步操作时,则无论哪种方式都...
ios demo,dispatch_once,单例模式的应用,ios demo,dispatch_once,单例模式的应用
两种方式都是模拟任务block内为异步操作的情况,方式一先执行的dispatch_group_notify里的代码,后执行的dispatch_group_async里的任务代码,这与我们的初衷相违背。如果任务block内为同步操作时,则无论哪种方式都...
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ // do something ... dispatch_async(dispatch_get_main_queue(), ^{ [hud hideAnimated:YES]; }); }); 标签...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ // [NSThread sleepForTimeInterval:1]; CustomUploadQueue *upQueue = [[CustomUploadQueue alloc] init]; upQueue....
#definedispatch_get_main_queue() \DISPATCH_GLOBAL_OBJECT(dispatch_queue_t, _dispatch_main_q) 可以看出,dispatch_get_main_queue也是一种dispatch_queue_t。 2)并行队列global dispatch queue,通过dispa
the source code for particle swarm optimization algorithm is given in this file. the source code is for economic dispatch problem which is a power system problem.
Manifest_Dispatch_Air_Delete_6202_3
Manifest_Dispatch_Air_6202_2
Matlab m file for economic dispatch.
异步OC 用Objective-C重写... 代替熟悉的GCD语法: dispatch_async (dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{ NSLog ( @" A: This is run on the background " ); dispatch_async ( dis
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue); dispatch_source_...
Economic Dispatch Problem with GA
ios开发GCD的dispatch_semaphore:1、常用函数及作用 2、信号量的用途:1》同步不同线程 2》当做锁来使用:3》控制同时执行的线程数:
改进粒子群算法及其在电力系统经济负荷分配中的应用改进粒子群算法及其在电力系统经济负荷分配中的应用