我和greenDAO一起去了,到目前为止它进展顺利。有些事情似乎没有被文档或网站(或任何地方:()所涵盖,它是如何处理线程安全的。
我知道其他地方提到的基础知识,例如"使用单个dao会话" (Android + SQLite的一般做法),我非常了解Java内存模型。库内部甚至看起来是线程安全的,或者至少是用这种意图构建的。但我所看到的并没有涵盖这一点:
greenDAO默认缓存实体。这对于完全单线程程序非常有用 - 透明且大多数用途都可以提升性能。但如果我,例如loadAll()
然后修改其中一个元素,我在我的应用中修改同一个全局对象。如果我在主线程上使用它(例如用于显示),并在后台线程上更新数据库(正确和正确),除非特别小心,否则会出现明显的线程问题。
greenDAO做了什么"引擎盖下#34;防止常见的应用程序级线程问题?例如,修改UI线程中的缓存实体,同时将其保存在后台线程中(更希望它们不会交错!特别是在修改列表时!)?是否有任何"最佳做法"为了防范它们,除了一般的线程安全问题(即greenDAO期望和适用的东西)?或者从多线程应用程序的安全角度看整个缓存是否存在致命缺陷?
答案 0 :(得分:1)
我没有使用greenDA的经验,但是这里的文档: http://greendao-orm.com/documentation/queries/
表示:
如果在多个线程中使用查询,则必须在查询上调用forCurrentThread()以获取当前线程的Query实例。从greenDAO 1.3开始,Query的对象实例绑定到构建查询的拥有线程。这使您可以安全地在Query对象上设置参数,而其他线程不会干扰。如果其他线程尝试在查询上设置参数或执行绑定到另一个线程的查询,则会抛出异常。像这样,您不需要同步语句。实际上,您应该避免锁定,因为如果并发事务使用相同的Query对象,这可能会导致死锁。
为了完全避免这些潜在的死锁,greenDAO 1.3引入了CurrentThread()的方法。这将返回Query的线程本地实例,可以安全地在当前线程中使用。每次调用forCurrentThread()时,参数都会在使用其构建器构建查询时设置为初始参数。
虽然我可以看到文档没有明确说明除此之外的多线程,但这似乎很清楚它已被处理。这是在讨论使用相同Query对象的多个线程,因此很明显多个线程可以访问同一个数据库。当然,数据库和DAO处理并发访问是正常的,在这种情况下有很多经过验证的技术可以用来处理缓存。
答案 1 :(得分:0)
默认情况下,GreenDAO缓存并返回缓存的实体实例以提高性能。要防止出现这种情况,您需要调用:
daoSession.clear()
清除所有缓存的实例。或者,您可以致电:
objectDao.detachAll()
仅清除特定DAO对象的缓存实例。
每次要清除缓存的实例时都需要调用这些方法,因此如果要禁用所有缓存,我建议您在Session或DAO访问器方法中调用它们。