如何保证contentprovider线程的安全性

在实现ContentProviders时,一个常见的混淆来源是线程安全。我们都知道任何潜在的昂贵的查询应该是异步的,以便不阻塞UI线程,但是如果有的话,什么时候可以从多个线程调用ContentProvider呢?

线索和内容提供者

关于ContentProviders的文档警告说,它的方法可能会被多线程调用,因此必须是线程安全的:

数据访问方法(如insert(Uri,ContentValues)和update(Uri,ContentValues,String,String[]))可以同时从多个线程调用,并且必须是线程安全的。

换句话说,Android不会为您同步对ContentProvider的访问。如果两个不同的线程同时调用同一个方法,则任何一个调用都不会等待另一个。从框架开发人员的角度来看,要求客户端自己处理并发是有道理的。abstractContentProvider类不能假定它的子类需要同步,因为这样做效率会低得可怕。

确保线程安全

那么现在我们知道了ContentProvider不是线程安全的,我们需要做什么来消除潜在的竞争条件呢?只是让每个方法同步,对吗?

良好的...不,不一定。考虑一个使用SQLiteDatabaseas作为后台数据源的ContentProvider。根据文档,默认情况下,对SQLiteDatabase的访问是同步的,从而保证不会有两个线程同时访问它。在这种情况下,同步ContentProvider的每个方法既没有必要,成本也很高。请记住,ContentProvider充当底层数据源的包装器;是否必须采取额外的措施来确保线程安全通常取决于数据源本身。

结论

尽管ContentProvider缺乏线程安全性,但您经常会发现,在防止潜在的竞争情况方面,您不需要采取进一步的措施。典型的例子是当您的ContentProvider由SQLiteDatabase支持时;当两个线程试图同时写入数据库时,SQLiteDatabase会锁定自己,确保一个线程等待另一个线程完成。每个线程将被授予对数据源的互斥访问权,以确保满足线程安全性。

ref:/2012/10/SQLite-content provider-thread-safety . html

上面作者提到,在内容提供者的实现中没有考虑线程安全,所以在访问内容提供者的时候,要确保不会有多个线程同时访问。如果多个线程同时访问数据库,它们会锁定自己,这不会导致数据丢失,但可能会报告数据库被锁定的异常。