用`dispatch_barrier`死锁
通过学习dispatch_barrier
,我写了一个例子如下:
static dispatch_queue_t queue; static dispatch_queue_t readWriteLockQueue; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ queue = dispatch_queue_create("com.test.testasync", DISPATCH_QUEUE_CONCURRENT); readWriteLockQueue = dispatch_queue_create("com.test.readWriteLockQueueOfMeta", DISPATCH_QUEUE_CONCURRENT); }); for (NSInteger i=0; i<100; i++) { dispatch_async(queue, ^{ dispatch_sync(readWriteLockQueue, ^{ NSLog(@"read"); }); dispatch_barrier_sync(readWriteLockQueue, ^{ NSLog(@"write"); }); }); } dispatch_barrier_async(queue, ^{ NSLog(@"finished!"); });
但是输出结果是:
2016-05-20 16:23:14.066 Test[23867:781553] read 2016-05-20 16:23:14.066 Test[23867:781555] read 2016-05-20 16:23:14.066 Test[23867:781554] read 2016-05-20 16:23:14.066 Test[23867:781545] read 2016-05-20 16:23:14.066 Test[23867:781559] read 2016-05-20 16:23:14.067 Test[23867:781564] read 2016-05-20 16:23:14.066 Test[23867:781560] read 2016-05-20 16:23:14.066 Test[23867:781561] read 2016-05-20 16:23:14.067 Test[23867:781562] read 2016-05-20 16:23:14.067 Test[23867:781565] read
没有write
出现。 这超出了我的预期。 所以我需要一些帮助。
dispatch_barrier_sync
或dispatch_sync
没有调用里面的sync
。 为什么会发生死锁?
更新:感谢@ originaluser2的回答。 我使用下面的读写锁更新了我的工具,以避免虚拟线程限制。
#define THREAD_ASSERT_ON_ERROR(x_) do { \ _Pragma("clang diagnostic push"); \ _Pragma("clang diagnostic ignored \"-Wunused-variable\""); \ volatile int res = (x_); \ assert(res == 0); \ _Pragma("clang diagnostic pop"); \ } while (0) static dispatch_queue_t queue; static dispatch_once_t onceToken; static pthread_rwlock_t rwlock; dispatch_once(&onceToken, ^{ queue = dispatch_queue_create("com.test.testasync", DISPATCH_QUEUE_CONCURRENT); THREAD_ASSERT_ON_ERROR(pthread_rwlock_init(&rwlock, NULL)); }); NSMutableDictionary *dict = [NSMutableDictionary dictionary]; for (NSInteger i=0; i<200; i++) { dispatch_async(queue, ^{ NSString *result = nil; THREAD_ASSERT_ON_ERROR(pthread_rwlock_rdlock(&rwlock)); result = dict[@"test"]; THREAD_ASSERT_ON_ERROR(pthread_rwlock_unlock(&rwlock)); if (!result) { THREAD_ASSERT_ON_ERROR(pthread_rwlock_wrlock(&rwlock)); NSLog(@"%ld:try to write",i); result = dict[@"test"]; if (!result) { NSLog(@"%ld:write",i); dict[@"test"] = @"result"; result = dict[@"test"]; } THREAD_ASSERT_ON_ERROR(pthread_rwlock_unlock(&rwlock)); } NSLog(@"%ld:%@",i,result); }); } dispatch_barrier_sync(queue, ^{}); NSLog(@"completed");
问题是你正在安排100个任务并发执行。 这将超过虚拟线程的限制(通常是64) – 因此,您将有64个任务等待他们的读取或写入完成,但是他们无法完成,因为没有更多的线程可以完成它们。
如果你将循环降低到64,或者让你的queue
成为一个串行队列,以便瓶颈任务,代码将再次工作。 虽然这是一个相当人为的例子。 实际上,你永远不会有这么多有争议的读写同时发生(这将表明你的逻辑中存在一个更基本的问题) – 即使你这样做,你的写入应该很可能与dispatch_barrier_async
asynchronous发生。