Поточная обработка Android и блокировка базы данных

Мы используем AsyncTasks к таблицам базы данных доступа и курсорам.

К сожалению, мы видим, что случайные исключения расценивают заблокированную базу данных.

E/SQLiteOpenHelper(15963): Couldn't open iviewnews.db for writing (will try read-only):
E/SQLiteOpenHelper(15963): android.database.sqlite.SQLiteException: database is locked
E/SQLiteOpenHelper(15963):  at     android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
E/SQLiteOpenHelper(15963):  at     android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1637)
E/SQLiteOpenHelper(15963):  at     android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1587)
E/SQLiteOpenHelper(15963):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:638)
E/SQLiteOpenHelper(15963):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:659)
E/SQLiteOpenHelper(15963):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:652)
E/SQLiteOpenHelper(15963):  at android.app.ApplicationContext.openOrCreateDatabase(ApplicationContext.java:482)
E/SQLiteOpenHelper(15963):  at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:193)
E/SQLiteOpenHelper(15963):  at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98)
E/SQLiteOpenHelper(15963):  at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:158)
E/SQLiteOpenHelper(15963):  at com.iview.android.widget.IViewNewsTopStoryWidget.initData(IViewNewsTopStoryWidget.java:73)
E/SQLiteOpenHelper(15963):  at com.iview.android.widget.IViewNewsTopStoryWidget.updateNewsWidgets(IViewNewsTopStoryWidget.java:121)
E/SQLiteOpenHelper(15963):  at com.iview.android.async.GetNewsTask.doInBackground(GetNewsTask.java:338)
E/SQLiteOpenHelper(15963):  at com.iview.android.async.GetNewsTask.doInBackground(GetNewsTask.java:1)
E/SQLiteOpenHelper(15963):  at android.os.AsyncTask$2.call(AsyncTask.java:185)
E/SQLiteOpenHelper(15963):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:256)
E/SQLiteOpenHelper(15963):  at java.util.concurrent.FutureTask.run(FutureTask.java:122)
E/SQLiteOpenHelper(15963):  at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:648)
E/SQLiteOpenHelper(15963):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:673)
E/SQLiteOpenHelper(15963):  at java.lang.Thread.run(Thread.java:1060)

У кого-либо есть общий пример для кода, который пишет в базу данных от другого потока, чем чтение того и как мы можем гарантировать потокобезопасность.

Одно предложение, которое я имел, состоит в том, чтобы использовать a ContentProvider, поскольку это обработало бы доступ базы данных от нескольких потоков. Я собираюсь посмотреть на это, но действительно ли это - рекомендуемый метод решения такой проблемы? Это кажется довольно тяжелым рассмотрением, что мы говорим о впереди или позади.

28
задан Idolon 15 February 2012 в 12:19
поделиться

3 ответа

Вы говорите об одном действии пользователя, которое внутри вашей программы вызывает выполнение нескольких потоков, несколько из которых могут обращаться к базе данных в режим обновления?

Это плохой дизайн, точка. Вы не можете узнать, в каком порядке потоки будут планироваться вашей ОС (/ VM), и, следовательно, вы не можете узнать, в каком порядке будет происходить доступ к базе данных, и это, скорее всего, будет означать что вы не можете знать, что доступ к базе данных всегда будет происходить в ожидаемом вами порядке.

Все обращения к базе данных, сгенерированные / исходящие от какого-либо действия пользователя, должны выполняться в одном потоке.

-6
ответ дан 28 November 2019 в 03:04
поделиться

Учтите, что базы данных SQLite основаны на файлах и не предназначены для многопроцессорного доступа. Лучшая процедура смешивания SQLite с мультиобработкой - использование семафоров (aquire (), release ()) в каждом доступе, связанном с базой данных.

Если вы создаете оболочку БД, которая получает / освобождает глобальный семафор, ваш доступ к БД будет потокобезопасным. На самом деле это означает, что вы можете получить бутлинек, потому что вы ставите в очередь доступ к БД. Таким образом, кроме того, вы можете обернуть доступ с помощью семафоров только в том случае, если это операция, изменяющая базу данных, поэтому, пока вы изменяете базу данных, никто не сможет получить к ней доступ и дождаться завершения процесса записи.

9
ответ дан 28 November 2019 в 03:04
поделиться

Мы использовали ContentProvider в конец. Похоже, это прояснило проблемы.

28
ответ дан 28 November 2019 в 03:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: