java – SQLiteDatabase多线程锁定模式

前端之家收集整理的这篇文章主要介绍了java – SQLiteDatabase多线程锁定模式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我使用这个类来管理与底层sqlite Database的连接
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();
    }
}

它包含两个锁,一个用于读取,第二个用于写入.
但我还是偶尔得到这样的例外:

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)

这意味着,当尝试在getWritableDatabase中获取锁定时,数据库被某种方式锁定.

我的sqliteOpenHelper是单例模式,DataSources只使用BasicDataSource作为父类.

可以做什么改进,以避免sqliteDatabaseLockedException在显示代码

解决方法

sqlite中,可以有任意多的读者,但任何作家都会阻止所有其他读者和作家.

您必须为读者和作家使用单一的锁.

请注意,只要您实际访问数据库,锁必须保持.

如果要支持多个读取器,请使用实现ReadWriteLock的锁,例如ReentrantReadWriteLock.这样的东西:

class MyData {
    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    private final Lock r = rwl.readLock();
    private final Lock w = rwl.writeLock();

    public Data ReadSomething(int id) {
        r.lock();
        try {
            Cursor c = readableDatabase.query(...);
            return c.getString(0);
        } finally {
            r.unlock();
        }
    }

    public void ChangeSomething(int id,int value) {
        w.lock();
        try {
            writeableDatabase.update(...);
        } finally {
            w.unlock();
        }
    }
}
原文链接:https://www.f2er.com/java/123321.html

猜你在找的Java相关文章