我的Android应用程序中有一定的更新方法,可生成大量数据 - 最多可达数百个数据库条目。 除了UI线程之外,我还有一个后台服务。两个线程都必须执行更新方法,有时甚至是在同一时间 - 基本上,这是关于生成和缓存要显示的数据。 UI和后台服务都需要这些数据。
目前,我已将方法的执行包装在ORMLite事务中,该事务映射到普通的SQLite事务。但是,有一天,当一些竞争条件搞砸了数据缓存时,我担心这会让我陷入困境。
问题:SQLite事务是否可以保护我免受并发执行的影响,还是应该实现某种工作线程,这种线程在生成器方法启动时生成,或者阻塞生成器方法是否已经运行?
更新
我决定不依赖SQLite逻辑来保护我的高级Java方法。解决方案对我来说如下:
synchronized
synchronized
部分中的第一件事,检查上次执行是否在特定阈值(例如,过去的< = 100ms)
这样,不应该进行重复生成,因为当同时从两个线程访问该方法时,第一个将生成,但第二个不生成。对我来说最重要的部分是它仍然是阻塞的,因为两个线程都依赖于在调用方法之后发生的一代。
答案 0 :(得分:0)
修改强>
在我的下面的陈述中似乎我错了:根据许多人的说法,SQLite实现是线程安全的。但是,我遇到了严重的线程问题,特别是在测试数据库访问时,但这必定是由我的代码中的其他因素引起的,我认为。
对于误导性的回答感到抱歉。
<强> ORIGIN:强>
好问题!
这里你应该非常小心因为标准的Android数据库访问对象(例如 SQLiteDatabase
,Cursor
等)默认情况下不是线程安全的。除非你明确地用多线程编写它们,否则ContentProvider
似乎不会给你一个完整的保护。
根据ContentProvider
上的Android documentation和线程(几乎在页面末尾):
“因为这些方法[
update()
是其中一个函数]可能同时从任意数量的线程调用,所以它们也必须实现为线程安全的。”
我不知道SQLiteDatabases是否有任何明确的锁定机制(如锁定实际的数据库文件)。我假设一个事务本身会锁定,至少是你访问数据库的句柄。我不知道你的数据库有多个句柄的情况是什么。
也许您可以尝试实现一些单例对象(可能是ContentProvider
?)来访问您的数据库,但即使这样,您也必须管理某种“请求队列”。
您还应该考虑 not 从UI线程对文件系统(数据库在文件系统上)进行任何调用,无论如何。无法保证数据库能够及时回答并且您可能最终得到ANR(特别是当您编写"...which generates quite an amount of data"
时)。