用`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_syncdispatch_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_asyncasynchronous发生。