编辑:事实上,信号量与背景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];
以下是我如何管理对DB的访问:
- (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);
}
答案 0 :(得分:0)
dispatch_semaphore_wait适用于并发后台NSOperation。
但是下次我应该考虑将优先级低的背景添加到队列后取消,但之前它有时间启动。在这种情况下,在我的实现中,此操作的completionBlock对dispatch_semaphore_signal进行了额外的调用,这会产生dispatch_semaphore_wait的“神秘”错误