SQLiteDatabase modèle de verrouillage multi-thread
J'utilise cette classe pour gérer la connexion sous-jacente SQLiteDatabase
public class BasicDataSource {
protected DatabaseHandler dbHelper;
protected volatile SQLiteDatabase readable_database;
protected volatile SQLiteDatabase writable_database;
protected Object read_lock = new Object();
protected Object write_lock = new Object();
protected Context context;
protected BasicDataSource(Context ctx) {
dbHelper = DatabaseHandler.getInstance(ctx);
getReadableDatabase();
dbHelper.onCreate(getWritableDatabase());
this.context = ctx;
}
public synchronized void close() {
dbHelper.close();
}
protected void closeInsertHelpers(InsertHelper... helpers) {
for (InsertHelper ih : helpers) {
if (ih != null)
ih.close();
}
}
protected SQLiteDatabase getReadableDatabase() {
synchronized (read_lock) {
if (readable_database == null || !readable_database.isOpen()) {
readable_database = dbHelper.getReadableDatabase();
}
return readable_database;
}
}
protected SQLiteDatabase getWritableDatabase() {
synchronized (write_lock) {
if (writable_database == null || !writable_database.isOpen()) {
writable_database = dbHelper.getWritableDatabase();
}
return writable_database;
}
}
protected synchronized void open() throws SQLException {
getReadableDatabase();
getWritableDatabase();
}
}
Il contient deux verrous, l'un pour la lecture, le second pour l'écriture.
Mais je suis encore de temps en temps de recevoir ce genre d'exception:
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:299)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Caused by: android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:882)
at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:627)
at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:313)
at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:287)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:804)
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
at com.mycompany.myapplication.sql.BasicDataSource.getWritableDatabase(BasicDataSource.java:57)
at com.mycompany.myapplication.sql.datasources.SomeDataSource.fillUpDatabaseMethod(SomeDataSource.java:264)
at com.mycompany.myapplication.sql.datasources.SomeDataSource.renewCacheMethod(SomeDataSource.java:560)
at com.mycompany.myapplication.activities.lists.ListsActivity$Worker.doInBackground(ListsActivity.java:315)
at com.mycompany.myapplication.activities.lists.ListsActivity$Worker.doInBackground(ListsActivity.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
... 4 more
android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:882)
at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:627)
at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:313)
at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:287)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:804)
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
at com.mycompany.myapplication.sql.BasicDataSource.getWritableDatabase(BasicDataSource.java:57)
at com.mycompany.myapplication.sql.datasources.SomeDataSource.fillUpDatabaseMethod(SomeDataSource.java:264)
at com.mycompany.myapplication.sql.datasources.SomeDataSource.renewCacheMethod(SomeDataSource.java:560)
at com.mycompany.myapplication.activities.lists.ListsActivity$Worker.doInBackground(ListsActivity.java:315)
at com.mycompany.myapplication.activities.lists.ListsActivity$Worker.doInBackground(ListsActivity.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Ce qui signifie, la base de données est en quelque sorte verrouillé lorsque vous essayez d'acquérir de verrouillage dans getWritableDatabase.
Mon SQLiteOpenHelper est un singleton, et les Sources de données sont uniquement à l'aide de BasicDataSource comme classe parente.
Qu'est-ce que l'amélioration que je peut faire pour éviter de SQLiteDatabaseLockedException dans le code montré?
source d'informationauteur Marek Sebera
Vous devez vous connecter pour publier un commentaire.
Dans SQLite, il ne peut être arbitrairement de nombreux lecteurs, mais tout écrivain bloque tous les autres lecteurs et d'écrivains.
Vous devez utiliser un verrou unique pour à la fois les lecteurs et les écrivains.
Veuillez noter que les serrures doivent être tenus aussi longtemps que vous êtes en train de consulter la base de données.
Si vous voulez le soutien de plusieurs lecteurs, l'utilisation d'un verrou qui implémente
ReadWriteLock
commeReentrantReadWriteLock
. Quelque chose comme ceci: