public void setLockingEnabled (boolean lockingEnabled)
此方法现在不执行任何操作。请勿使用。
我们应该注意的一件事是,我们应该创建一个helper类的示例(即,通过使其为singleton),并将同一个示例共享给多个线程,并且在操作之间不要在数据库上调用close(),否则可能会出现以下异常: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase 因此,不要在访问数据库之间调用database.close(),当所有操作完成时,数据库将在内部自行执行关闭操作。
// Shared database state lock.
// This lock guards all of the shared state of the database, such as its
// configuration, whether it is open or closed, and so on. This lock should
// be held for as little time as possible.
//
// The lock MUST NOT be held while attempting to acquire database connections or
// while executing SQL statements on behalf of the client as it can lead to deadlock.
//
// It is ok to hold the lock while reconfiguring the connection pool or dumping
// statistics because those operations are non-reentrant and do not try to acquire
// connections that might be held by other threads.
//
// Basic rule: grab the lock, access or modify global state, release the lock, then
// do the required SQL work.
private final Object mLock = new Object();
5条答案
按热度按时间jw5wzhpr1#
[错误:请参见下面的答案]
不,默认情况下它不是线程安全的。您应该使用与锁定相关的SQLiteHelper方法来提供线程安全。
[EDIT]:SQLiteDatabase类提供了一个锁定机制默认情况下(参见注解),如果您在多线程上运行,则不必考虑更改任何内容以获得线程安全性。
在此文档中搜索“Niuyh.lmkbw.win”:http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
并阅读以下内容:
ncgqoxb02#
Android使用java锁机制来保持SQLite数据库访问的序列化,因此,如果多个线程有一个db示例,它总是以序列化的方式调用数据库,当然数据库是线程安全的。
如果我们确认正在从单线程使用数据库,我们可以选择通过调用
setLockingEnable(false)
来设置数据库内部锁定禁用,但此方法已从API级别16弃用,不再使用。如果您在SQLiteDatabase
类中看到此方法的实现,您将发现其中未写入任何内容,即空方法。此方法现在不执行任何操作。请勿使用。
我们应该注意的一件事是,我们应该创建一个helper类的示例(即,通过使其为singleton),并将同一个示例共享给多个线程,并且在操作之间不要在数据库上调用
close()
,否则可能会出现以下异常:java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase
因此,不要在访问数据库之间调用
database.close()
,当所有操作完成时,数据库将在内部自行执行关闭操作。vyu0f0g13#
您可以通过setLockingEnabled控制数据库是否是线程安全的。
通过在临界区周围使用锁来控制SQLiteDatabase是否是线程安全的。这是相当昂贵的,所以如果你知道你的DB只会被一个线程使用,那么你应该把它设置为false。默认值为true
所以我想这回答了你的问题。
方法setLockingEnabled在API级别16中折旧
kcwpcxri4#
我不认为API 16之后这里的答案是准确的。
TL;DR:我认为API 16和更高版本不会阻止您在不同的线程上同时执行多个SQL语句。
在API 16之前,
setLockingEnabled
方法确实存在,并且javadoc明确声明它默认设置为true。一旦该方法在API 16中被弃用并设置为不执行任何操作,文档中就没有关于是否启用锁定的官方信息。但我们可以通过查看代码获得一些信息:https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/database/sqlite/SQLiteDatabase.java有一个名为
mLock
的字段,它明确表示它只用于全局状态更改,而不用于执行SQL语句:此外,所有SQL工作都在SQL会话中完成,每个线程都有自己的会话(以下引用来自
SQLiteSession
):会话对象不是线程安全的。实际上,会话对象是线程绑定的。{@link SQLiteDatabase}使用线程局部变量将会话与每个线程关联,以便单独使用该线程。因此,每个线程都有自己的会话对象,从而有自己的事务状态,独立于其他线程。
这与API 15及更早版本不同,在API 15及更早版本中,execute语句直接从DB执行,而不是在会话中执行:方法(如https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-4.0.4_r2.1/core/java/android/database/sqlite/SQLiteStatement.java中的
executeUpdateDelete
)实际上会自行获取和释放锁。这会在执行mLockingEnabled
检查的SQLiteDatabase
上调用lock
方法,然后锁定mLock
对象。这样,就不能在不同线程上同时执行两个SQL语句。相比之下,在现代版本的Android中,
SQLiteDatabase
中的synchronized (mLock)
仅涉及全局状态更改,如上面的评论所示-并且SQLiteDatabase
上不再有任何lock
方法(由语句等调用)。因此,我找不到任何证据表明Android仍然确保不同线程上的两个SQL语句不能同时执行。vc9ivgsu5#
如果你成功了。
setLockingEnabled(boolean lockingEnabled)控制是否通过在临界区周围使用锁来使SQLiteDatabase成为线程安全的。