Android multi-thread secure database access

Source: Internet
Author: User

To record how threads securely access your Android database instance, I wrote this little note. For the project code referenced in this article, click here to assume that you have compiled your own SQLiteOpenHelper.

publicclassDatabaseHelperextendsSQLiteOpenHelper{...}

Now you want to write data to the database in different threads:

// Thread 1Context context = getApplicationContext();DatabaseHelper helper =newDatabaseHelper(context);SQLiteDatabase database = helper.getWritableDatabase(); database.insert(…); database.close();// Thread 2Context context = getApplicationContext();DatabaseHelper helper =newDatabaseHelper(context);SQLiteDatabase database = helper.getWritableDatabase(); database.insert(…); database.close();

Then, the log information similar to the following will be output in your Logcat, and your write data operation will be invalid.

android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)

The above problem occurs because every time you create a SQLiteOpenHelper object, you are actually creating a database connection. If you try to write data to the database through multiple connections at the same time, it will certainly fail.

To ensure that we can operate databases securely in multiple threads, we need to ensure that only one database connection is occupied.

First, we compile a single DatabaseManager that manages a single SQLiteOpenHelper object.

publicclassDatabaseManager{privatestaticDatabaseManager instance;privatestaticSQLiteOpenHelper mDatabaseHelper;publicstaticsynchronizedvoid initialize(Context context,SQLiteOpenHelper helper){if(instance ==null){            instance =newDatabaseManager();            mDatabaseHelper = helper;}}publicstaticsynchronizedDatabaseManager getInstance(){if(instance ==null){thrownewIllegalStateException(DatabaseManager.class.getSimpleName()+" is not initialized, call initialize(..) method first.");}return instance;}publicsynchronizedSQLiteDatabase getDatabase(){returnnew mDatabaseHelper.getWritableDatabase();}} 

To write data in multiple threads, modify the Code as follows:

// In your application classDatabaseManager.initializeInstance(getApplicationContext());// Thread 1DatabaseManager manager =DatabaseManager.getInstance();SQLiteDatabase database = manager.getDatabase() database.insert(…); database.close();// Thread 2DatabaseManager manager =DatabaseManager.getInstance();SQLiteDatabase database = manager.getDatabase() database.insert(…); database.close();

Then another crash occurs.

java.lang.IllegalStateException: attempt to re-open an already-closed object:SQLiteDatabase

Since we only have one database connection, the call to the getDatabase () method of Thread1 and Thread2 will obtain the same SQLiteDatabase object instance. The next thing is that when Thread1 tries to manage the database connection, Thread2 is still using the database connection. This is the cause of the failure of IllegalStateException.

Therefore, we can only disable the database when it is no longer in use. We recommend "never close" Your SQLiteDatabase in stackoveflow. If you do this, the following information will appear in your logcat, so I don't think this is a good idea.
Leak foundCaused by: java.lang.IllegalStateException:SQLiteDatabase created and never closed

Example:

publicclassDatabaseManager{privateAtomicInteger mOpenCounter =newAtomicInteger();privatestaticDatabaseManager instance;privatestaticSQLiteOpenHelper mDatabaseHelper;privateSQLiteDatabase mDatabase;publicstaticsynchronizedvoid initializeInstance(SQLiteOpenHelper helper){if(instance ==null){            instance =newDatabaseManager();            mDatabaseHelper = helper;}}publicstaticsynchronizedDatabaseManager getInstance(){if(instance ==null){thrownewIllegalStateException(DatabaseManager.class.getSimpleName()+" is not initialized, call initializeInstance(..) method first.");}return instance;}publicsynchronizedSQLiteDatabase openDatabase(){if(mOpenCounter.incrementAndGet()==1){// Opening new database            mDatabase = mDatabaseHelper.getWritableDatabase();}return mDatabase;}publicsynchronizedvoid closeDatabase(){if(mOpenCounter.decrementAndGet()==0){// Closing database            mDatabase.close();}}}

Then how can you call it:

SQLiteDatabase database =DatabaseManager.getInstance().openDatabase();database.insert(...);// database.close(); Don't close it directly!DatabaseManager.getInstance().closeDatabase();// correct way

In the future, whenever you need to use a database connection, you can call the DatabaseManager-class method openDatabase (). In the method, there is a built-in counter that indicates how many times the database is opened. If the count is 1, we need to open a new database connection. Otherwise, the database connection already exists.

The same is true in method closeDatabase. Every time we call the closeDatabase () method, the counter will decrease until the count is 0, and we need to close the database connection.

Tip: You should use AtomicInteger to handle concurrency

Now you can use your database connection in a thread-safe manner.

 

Original article: https://github.com/dmytrodanylyk/dmytrodanylyk/blob/gh-pages/articles/Concurrent%20Database%20Access.md

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.