【发布时间】:2016-12-12 13:35:09
【问题描述】:
编辑:事实上,信号量与后台 NSOperation 完美配合,问题是有时操作在在有机会开始之前就被取消了,这会产生对 dispatch_semaphore_signal 的额外调用并允许在不停止线程的情况下传递两个 dispatch_semaphore_wait。
我的 iOS 应用程序使用 sqlite 数据库作为数据存储(由于历史原因没有使用 CoreData)。当少数线程同时访问一个数据库连接时,sqlite 会崩溃,因此我使用 dispatch_semaphore_wait 并在数据库打开时将信号量激活为 dispatch_semaphore_create(1)。
在我实现了一种数据库访问方法作为 NSOperation(我需要取消功能)后,我的应用程序开始崩溃,我意识到即使数据库已经很忙,dispatch_semaphore_wait 也不会暂停线程。这通常发生在我从主线程执行快速数据库调用时,该调用与封装到 NSOperation 的更大调用重叠。
这里是创建 NSOperation 的代码:
self.loadOperation = [NSBlockOperation blockOperationWithBlock:^{
[database openDatabase];
// read some data
}
self.loadOperation.queuePriority = NSOperationQueuePriorityLow;
self.loadOperation.qualityOfService = NSOperationQualityOfServiceUtility;
self.loadOperation.completionBlock = ^{
[database closeDatabase];
};
NSOperationQueue* backgroundQueue = [[NSOperationQueue alloc] init];
[backgroundQueue addOperation:self.loadOperation];
这是我管理对数据库的访问的方式:
- (instancetype)init
{
if ( self = [super init] ) {
databaseOpenSemaphore = dispatch_semaphore_create(1);
}
return self;
}
- (void)openDatabase
{
dispatch_semaphore_wait(databaseOpenSemaphore, DISPATCH_TIME_FOREVER);
// open DB
}
- (void)closeDatabase
{
// close DB
dispatch_semaphore_signal(databaseOpenSemaphore);
}
【问题讨论】:
-
这两个sn-ps的代码分别对应哪个类?您能否为您发布的代码提供更多上下文,以便我们更好地了解您的主线程发生了什么以及您认为其他线程发生了什么导致崩溃?
-
这两个sn-ps属于两个很大的不同类,所以我只复制了有问题的部分。我还添加了崩溃时线程状态的屏幕截图。
-
问题是您没有提供足够的上下文让我们将所有部分链接在一起,您不需要发布整个源代码。
-
@Cristik 感谢您关注这件事,但很难提供更详细的上下文 - 周围发生了很多事情。我希望我能以某种方式缩小焦点,我抓住了执行意外通过信号量的时刻 - 请在帖子中查看我的编辑。
-
@Cristik 事实上这是我的错误,你是对的——它不可见,因为我简化了太多代码。感谢您的帮助!
标签: ios objective-c semaphore nsoperation