HR's Blog

Swimming 🏊 in the sea🌊of code!

0%

dispatch_get_specific

.

dispatch_get_specificdispatch_queue_set_specific 用法就是用set方法在线程里设置一个key,通过get查找当前线程,是不是包含该key来判断代码是不是在特定的线程里执行。set则是给线程设置key值。

1. Get

dispatch_get_specific设置Key值。

两种方法查询线程里面包含的key值

  • dispatch_get_specific:查询当前线程的key值。
  • dispatch_queue_get_specific: 查询特定线程的key值,需要传入线程。

2. Set

1
void dispatch_queue_set_specific(dispatch_queue_t queue, const void *key, void *context, dispatch_function_t destructor);

需要注意的是set方法的最后一个参数可以传入一个函数,当做析构函数。

3.示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const char *queueKey1 = "queueKey1";
const char *queueKey2 = "queueKey2";

void (^executionBlock)() = ^{
if(dispatch_get_specific(queueKey1)) {
printf("queueKey1");
} else if(dispatch_get_specific(queueKey2)) {
printf("queueKey2");
} else {
NSLog(@"other queue");
}
};

void queueFunction() {
NSLog(@"__queueFunction");
}
1
2
3
4
5
6
7
8
9
10
11
12
dispatch_queue_t queue1 = dispatch_queue_create(queueKey1, NULL);
dispatch_queue_t queue2 = dispatch_queue_create(queueKey2, NULL);

dispatch_queue_set_specific(queue1, queueKey1, &queueKey1, queueFunction);
dispatch_queue_set_specific(queue2, queueKey2, &queueKey2, NULL);

dispatch_sync(queue1, executionBlock);
dispatch_sync(queue2, executionBlock);

if (dispatch_queue_get_specific(queue1, queueKey1)) {
NSLog(@"包含");
}

运行结果

1
2
3
4
queueKey1
queueKey2
包含
__queueFunction

4. FMDB如何使用dispatch_queue_set_specific和dispatch_get_specific来防止死锁

作用类似objc_setAssociatedObject跟objc_getAssociatedObject

1
2
3
4
5
6
7
8
9
10
11
static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey;
//创建串行队列,所有数据库的操作都在这个队列里
_queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
//标记队列
dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge void *)self, NULL);

//检查是否是同一个队列来避免死锁的方法
- (void)inDatabase:(void (^)(FMDatabase *db))block {
FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);
assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock");
}

5. References