【问题标题】:Concurrent execution of two SQLite transactions in two threads在两个线程中同时执行两个 SQLite 事务
【发布时间】:2011-07-25 11:39:46
【问题描述】:

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

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

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

更新:

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

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

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

【问题讨论】:

标签: android multithreading sqlite transactions ormlite


【解决方案1】:

编辑:

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

对不起,误导性的答案。

起源:

好问题!

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

根据Android documentation 上的ContentProvider 和线程(几乎在页面末尾):

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

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

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

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

【讨论】:

  • AFAIK android 的 SQLite 实现确实是线程安全的,但我不确定并发事务执行 - 你知道吗?
  • 您提到的线程问题可能与使用多个数据库助手有关,这不是一个好主意。最好在 app 对象中保留一个 db-helper 实例。
  • 实际上,我总是只有一个数据库助手(通过艰难的方式学习 :-),但有时我也有第二个“纯”SQLiteDatabase 实例,我用它来操作测试数据库(大多数可能这是我做错了什么)。但没关系,我不想问你的问题:-)
猜你喜欢
  • 1970-01-01
  • 2019-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-19
  • 1970-01-01
  • 2013-10-19
  • 2020-07-16
相关资源
最近更新 更多