dan*_*kbx 7 sqlite iphone exc-bad-access objective-c fmdb
我正在使用FMDB处理我的数据库工作正常.该应用程序使用后台线程,它正在做一些工作,需要访问数据库.同时主线程需要在同一个数据库上运行一些查询.FMDB本身有一个小锁定系统,但是,我在我的类中添加了另一个.
只有当我的类指示数据库未使用时,才会执行每个查询.执行操作后,数据库将解锁.只要负载不是太高,这就可以正常工作.当我在主线程上运行的线程访问大量数据时,会发生EXC_BAD_ACCESS错误.
这是看起来:
- (BOOL)isDatabaseLocked {
return isDatabaseLocked;
}
- (Pile *)lockDatabase {
isDatabaseLocked = YES;
return self;
}
- (FMDatabase *)lockedDatabase {
@synchronized(self) {
while ([self isDatabaseLocked]) {
usleep(20);
//NSLog(@"Waiting until database gets unlocked...");
}
isDatabaseLocked = YES;
return self.database;
}
}
- (Pile *)unlockDatabase {
isDatabaseLocked = NO;
return self;
}
Run Code Online (Sandbox Code Playgroud)
调试器说错误发生[FMResultSet next]在该行
rc = sqlite3_step(statement.statement);
Run Code Online (Sandbox Code Playgroud)
我仔细检查了所有保留计数,此时所有对象都存在.同样,它只发生在主线程在后台线程运行时启动大量查询时(它本身总是产生很大的负载).错误总是由主线程产生,而不是由后台线程产生.
我的最后一个想法是两个线程同时运行lockedDatabase,这样他们就可以得到一个数据库对象.这就是我通过"@synchronized(self)"添加互斥锁定的原因.但是,这没有帮助.
有人有线索吗?
SQLite提供了更简单的序列化.通过设置sqlite_config()选项SQLITE_CONFIG_SERIALIZED,您可能会避免大多数这类令人头疼的问题.在与线程问题作斗争很长一段时间之后,我发现了这一点.
这是你如何使用它,你可以把它放在FMDatabase的init方法中......
if (sqlite3_config(SQLITE_CONFIG_SERIALIZED) == SQLITE_ERROR) {
NSLog(@"couldn't set serialized mode");
}
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅有关threadsafety和serialized模式的SQLite文档.
您应该在函数unlockDatabase 和lockDatabase 以及isDatabaseLocked 周围添加同步包装器——并不总是保证变量的存储或检索是原子的。当然,如果你这样做,你会想要将睡眠移到同步块之外,否则你会死锁。这本质上是一个自旋锁——它不是最有效的方法。
- (FMDatabase *)lockedDatabase {
do
{
@synchronized(self) {
if (![self isDatabaseLocked]) {
isDatabaseLocked = YES;
return self.database;
}
}
usleep(20);
}while(true); // continue until we get a lock
}
Run Code Online (Sandbox Code Playgroud)
您是否确保在调用unlockDatabase后不使用FMDatabase对象?您可能需要考虑句柄模式 - 创建一个包装 FMDatabase 对象的对象,并且只要它存在,就持有数据库的锁。在 init 中,您声明了锁,而在 dealloc 中,您可以释放该锁。那么你的客户端代码就不需要担心调用各种锁定/解锁函数,并且你不会意外地搞砸。尝试使用 NSMutex 而不是 @synchronized 块,请参阅http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8 -SW16