给出以下代码片段:
#import <XCTest/XCTest.h>
@interface DispatchTests : XCTestCase {
dispatch_queue_t _workQueue;
dispatch_queue_t _readWriteQueue;
int _value;
}
-(void)read;
-(void)write;
@end
@implementation DispatchTests
-(void)testDispatch {
_workQueue = dispatch_queue_create("com.work", DISPATCH_QUEUE_CONCURRENT);
_readWriteQueue = dispatch_queue_create("com.readwrite", DISPATCH_QUEUE_CONCURRENT);
_value = 0;
for(int i = 0; i < 100; i++) {
dispatch_async(_workQueue, ^{
if(arc4random() % 4 == 0) {
[self write];
} else {
[self read];
}
});
}
XCTestExpectation* expectation = [self expectationWithDescription:@"dude"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:6.0 handler:nil];
}
-(void)read {
dispatch_sync(_readWriteQueue, ^{
NSLog(@"read:%d", _value);
});
}
-(void)write {
dispatch_barrier_sync(_readWriteQueue, ^{
_value++;
NSLog(@"write:%d", _value);
});
}
@end这个测试的目的是看看我是否可以使用dispatch_barrier来管理读/写锁。在这个测试中,读者和作者都是同步的。当我使屏障异步的时候,测试似乎工作得很好,但是我想避免异步行为,因为这个实现是不平凡的。
我试图理解为什么write方法是死锁的。根据全球荒漠化理事会的文件:
当屏障块到达私有并发队列的前端时,它不会立即执行。相反,队列等待到当前执行的块完成执行。此时,队列自行执行屏障块。在屏障块之后提交的任何块在屏障块完成之前都不会执行。
我搞不懂“当前正在执行的块”是什么意思。
我的解释是这样的场景,其中一组读(x)被提交,然后是写(y),然后是更多的读(z):
发布于 2016-04-14 22:29:24
好的,在实际测试之后:您的代码不会在理论上阻塞。
然而--在实践中--它可能。
您正在经历的情况是,所有可用的系统线程都已耗尽。为了继续执行,您的代码将要求GCD获得一个新线程--但是non不再可用--因此,它会死锁。
为了避免这种情况,您需要分析您的代码,它以未绑定的方式生成新线程。这种情况可能发生在并发队列中,在这种情况下,块会阻塞或花费太长时间才能完成,并且会向该并发队列提交大量的块。
例如,如果插入一个小延迟:
for(int i = 0; i < 400; i++) {
usleep(1000);
dispatch_async(_workQueue, ^{
if(arc4random() % 4 == 0) {
[self write];
} else {
[self read];
}
});
}代码可以运行,直到它定期完成。当然,这只是为了证明问题-而不是解决你的问题。
https://stackoverflow.com/questions/36634315
复制相似问题