有greenDAO线程安全最佳实践吗?
Posted
技术标签:
【中文标题】有greenDAO线程安全最佳实践吗?【英文标题】:Are there greenDAO thread safety best practices? 【发布时间】:2014-08-12 22:34:44 【问题描述】:我正在尝试使用greenDAO,到目前为止一切顺利。文档或网站(或任何地方 :( )似乎没有涵盖的一件事是它如何处理线程安全。
我知道其他地方提到的基础知识,例如“使用单个 dao 会话”(android + SQLite 的一般做法),并且我非常了解 Java 内存模型。库内部结构甚至看起来是线程安全的,或者至少是为此目的而构建的。但我所见过的都没有涵盖这一点:
greenDAO 默认缓存实体。这对于完全单线程的程序来说是极好的——对于大多数用途来说是透明的和巨大的性能提升。但是如果我例如loadAll()
然后修改其中一个元素,我在我的应用程序中全局修改同一个对象。如果我在主线程上使用它(例如用于显示),并在后台线程上更新数据库(这是正确和正确的),除非格外小心,否则会出现明显的线程问题。
greenDAO 是否在“幕后”采取任何措施来防止常见的应用程序级线程问题?例如,修改 UI 线程中的缓存实体,同时将其保存在后台线程中(希望它们不要交错!尤其是在修改列表时!)?除了一般的线程安全问题(即 greenDAO 期望并与之配合良好的东西)之外,是否有任何“最佳实践”来防止它们?或者从多线程应用程序安全的角度来看,整个缓存是否存在致命缺陷?
【问题讨论】:
【参考方案1】:我没有使用 greenDAO 的经验,但这里的文档: http://greendao-orm.com/documentation/queries/
说:
如果在多个线程中使用查询,则必须在查询上调用 forCurrentThread() 以获取当前线程的 Query 实例。从 greenDAO 1.3 开始,Query 的对象实例绑定到它们自己的构建查询的线程。这使您可以安全地在 Query 对象上设置参数,而其他线程无法干预。如果其他线程尝试在查询上设置参数或执行绑定到另一个线程的查询,则会抛出异常。像这样,您不需要同步语句。事实上,您应该避免锁定,因为如果并发事务使用相同的 Query 对象,这可能会导致死锁。
为了完全避免这些潜在的死锁,greenDAO 1.3 引入了 forCurrentThread() 方法。这将返回 Query 的线程本地实例,可以在当前线程中安全使用。每次调用 forCurrentThread() 时,参数都会设置为使用其构建器构建查询时的初始参数。
虽然据我所知,文档并没有明确说明多线程,但除此之外,这似乎很清楚它已被处理。这是在谈论使用相同查询对象的多个线程,因此显然多个线程可以访问同一个数据库。当然,数据库和 DAO 处理并发访问是正常的,在这种情况下,有很多成熟的技术可以处理缓存。
【讨论】:
【参考方案2】:默认情况下,GreenDAO 缓存并返回缓存的实体实例以提高性能。为了防止这种行为,您需要调用:
daoSession.clear()
清除所有缓存的实例。或者,您可以致电:
objectDao.detachAll()
仅清除特定 DAO 对象的缓存实例。
每次您想清除缓存的实例时都需要调用这些方法,因此如果您想禁用所有缓存,我建议您在 Session 或 DAO 访问器方法中调用它们。
文档: http://greenrobot.org/greendao/documentation/sessions/#Clear_the_identity_scope 讨论:https://github.com/greenrobot/greenDAO/issues/776【讨论】:
以上是关于有greenDAO线程安全最佳实践吗?的主要内容,如果未能解决你的问题,请参考以下文章