I don't think the answers here are accurate anymore after API 16.
TL;DR: I think that API 16 and later don't stop you from executing multiple SQL statements at the same time on different threads.
Prior to API 16, the method setLockingEnabled
did exist and the javadoc clearly stated it was set to true by default. Once the method was deprecated in API 16 and set to do nothing, there is no official information in the docs about whether locking is enabled or not. But we can get some info by looking at the code: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/database/sqlite/SQLiteDatabase.java
There is a field called mLock
which explicitly says it's only used for global state changes and NOT for execution of SQL statements:
// 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();
Also, all the SQL work is done in SQL sessions and each thread has its own session (below quote is from SQLiteSession
):
Session objects are not thread-safe. In fact, session objects are thread-bound.
The {@link SQLiteDatabase} uses a thread-local variable to associate a session
with each thread for the use of that thread alone. Consequently, each thread
has its own session object and therefore its own transaction state independent
of other threads.
This is different from in API 15 and earlier, where execute statements were done directly from the DB and not in a session: methods such as executeUpdateDelete
in https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-4.0.4_r2.1/core/java/android/database/sqlite/SQLiteStatement.java actually acquire and release the lock themselves. This calls the lock
method on the SQLiteDatabase
which is where the check for mLockingEnabled
is performed and then locks the mLock
object. In this way, no two SQL statements can be executed at the same time on different threads.
In contrast, in modern versions of Android the synchronized (mLock)
in SQLiteDatabase
is only around global state changes, as indicated by the above comments - and there is no longer any lock
method on SQLiteDatabase
(to be called by statements etc) So I can't find any evidence that Android still ensures that two SQL statements on different threads can't be executed at the same time.