1

我的 Android 应用程序中有一个特定的更新方法,它会生成相当多的数据 - 多达数百个数据库条目。除了 UI 线程,我还有一个后台服务。两个线程都必须执行更新方法,有时甚至同时执行——基本上,这是关于生成和缓存要显示的数据。UI 和后台服务都需要这些数据。

目前,我已经将方法的执行包装在一个 ORMLite 事务中,该事务映射到一个普通的 SQLite 事务。但是,恐怕有一天,当某些竞争条件破坏了数据缓存时,这会咬我一口。

问题:SQLite 事务是否保护我免受并发执行,或者我应该实现某种在生成器方法启动时产生的工作线程,或者如果生成器方法已经运行则阻塞?

更新:

我决定不依赖 SQLite 逻辑来保护我的高级 Java 方法。解决方案对我来说如下:

  • 将方法的生成部分包装为synchronized
  • 引入一个变量,跟踪最后一次执行方法的时间(设置在方法的最后,所以它是执行结束的标志)
  • 本节中的第一件事synchronized,检查最后一次执行是否在特定阈值内(例如过去 <= 100ms)
    • 如果是,跳过生成
    • 如果没有,执行生成

这样,就不应该发生重复生成,因为当同时从两个线程访问该方法时,第一个会生成,而第二个不会。对我来说最重要的部分是它仍然是阻塞的,因为两个线程都依赖于它们调用该方法后发生的生成。

4

1 回答 1

0

编辑:

看来我在下面的陈述中是错误的: SQLite 实现,根据许多人的说法,是线程安全的。然而,我曾痛苦地经历过线程问题,尤其是在测试数据库访问时,但我认为那一定是由我的代码中的其他因素引起的。

对不起,误导性的答案。

起源:

好问题!

您在这里应该非常小心,因为标准的 Android 数据库访问对象(例如SQLiteDatabaseCursor)默认情况下不是线程安全的。甚至ContentProvider' 似乎都没有给你一个完整的保护,除非你明确地考虑到多线程来编写它们。

根据关于's 和 threading 的Android 文档ContentProvider(几乎在页面末尾):

“因为这些方法 [update()是功能之一] 可能会同时从任意数量的线程调用,因此它们也必须实现为线程安全的。”

我不知道 SQLiteDatabases 是否有任何显式锁定机制(如锁定实际数据库文件)。我会假设事务本身会锁定,至少是您访问数据库的句柄。我不知道对于您的数据库有多个句柄的情况是什么情况。

也许您可以尝试实现一些单例对象(ContentProvider也许是A?)来访问您的数据库,但即使这样,您也必须管理某种“请求队列”,我想。

您还应该考虑不要从 UI 线程对文件系统(数据库在文件系统上)进行任何调用。无法保证数据库会及时响应,并且您最终可能会遇到 ANR(尤其是在您编写时"...which generates quite an amount of data")。

于 2011-07-25T12:25:21.840 回答