我使用此类来管理与基础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();
}
}
它包含两个锁,一个用于读取,第二个用于写入。但是我仍然偶尔会遇到这种例外情况:
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();
}
}
}
我的问题是。。。为什么选择completionLock。run方法中的lock()未锁定资源。当我在系统中运行程序时。出来println(Thread.currentThread())。getName()) 我得到以下输出:Thread-1 Thread-0 Thread-0 Thread-1 NoLock ATM:130 Locked ATM:160应该是:160程序终止。 还有什么是等到完成才
问题内容: 我正在努力加快某些过程的执行速度,这些过程将大量记录(大多数是几百万个)发布到Elasticsearch。在我的C#代码中,我已经使用Dataflow实现了一个多线程解决方案,如下所示: 然后我要实现的发送批量请求调用: 我的问题 ,你 是对的实用性存在的数据流管道的一部分的锁内执行额外的线程。 这个可以吗?我可以在性能,执行,缓存/内存丢失等方面看到任何潜在的问题吗? 任何见识都会很
笔记摘要 这里介绍了java5中的线程锁技术:Lock和Condition,实现线程间的通信,其中的读锁和写锁的使用通过一个缓存系统进行了演示,对于Condition的应用通过一个阻塞队列进行演示。 线程锁技术:Lock & Condition 实现线程同步通信所属包:java.util.concurrent.locks 线程锁 说明 Synchronized 同步方法,锁对象是this;同步静态
我正在修改一个Java服务器软件。整个应用程序是单线程的。我的一个更改需要很多时间,所以我决定异步执行,以避免冻结主线程。 问题是:这种锁在Java中的最佳实现是什么?例如,我是否应该使用亲自完成。 编辑:看看我当前实现的答案。
我有一个类似的问题,但是我知道当我要求阅读一行时,发件人应该发送一个行尾。 让我困惑的是,在调试中,它是有效的。可能是因为我在调试时跳过的顺序(直到现在我都不知道这会有什么不同),但我想更好地理解它。 我已经使用线程,但不是很多。 这是我的服务器类: 线程(基于此) 和客户: 它似乎在某个地方进入了死锁,出于某种原因,除非在调试中运行,否则永远不要在向客户端发送数据的服务器类上输入该死锁 (顺便说
我想为strerror\u r调用创建线程本地缓冲区,并编写自己的线程安全字符*my\u strerror(int),它将使用线程本地缓冲区并调用strerror\r。 当阅读R. Stevens在Unix环境高级编程中关于pthread_getspecific()的例子时,我觉得差异-为什么在下面的例子中使用互斥锁? 书中的例子: