我正在使用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; }
调试器说错误发生[FMResultSet next]
在该行
rc = sqlite3_step(statement.statement);
我仔细检查了所有保留计数,此时所有对象都存在.同样,它只发生在主线程在后台线程运行时启动大量查询时(它本身总是产生很大的负载).错误总是由主线程产生,而不是由后台线程产生.
我的最后一个想法是两个线程同时运行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"); }
有关详细信息,请参阅有关threadsafety和serialized模式的SQLite文档.