1

I have two parts of a program (the actual app and a BroadcastReceiver) that could possibly try to connect to and modify a SQLite database and a SharedPreferences file.

1) I know you can make multiple connections to a single SQLite database. I also read that SQLite can "lock" the database when it attempts to modify or read from a database (UPDATE, INSERT, etc), so how do I properly handle the case where 2 threads try to modify/read a single SQLite database at the same time?

Right now, I have have this code snippet in my database connection code/class:

private SQLiteDatabase myDatabase;
public boolean insert(ContentValues columnValueMap) throws Exception
    {
        long result = 0;
        int attempt =0;
        do
        {
            if(!myDatabase.isDbLockedByOtherThreads() && !myDatabase.isDbLockedByCurrentThread())
            {
                synchronized (myDatabase)
                {
                    result=myDatabase.insertOrThrow(TABLE_NAME, TEXT, columnValueMap);
                    if(result ==0 || result == -1)
                    {
                        return false;
                    }
                    return true;
                }
            }
            else
            {
                Thread.sleep(50);
            }
            attempt++;
        }while(attempt<=5);

        throw new Exception("Database Locked!");
    }

2) Do I also have to worry about simultaneous access for a SharedPreferences file (It doesn't matter which thread gets access first, I'm just worried about errors being thrown)?

Thanks.

[EDIT] Proposed change

public boolean insert(ContentValues columnValueMap) throws Exception
    {
        long result = 0;
        synchronized (myDatabase)
        {
            result=myDatabase.insertOrThrow(TABLE_NAME, SMS_TEXT, columnValueMap);

            if(result ==0 || result == -1)
            {
                return false;
            }
            return true;
        }
    }

1 Answer 1

4

First of all, databases have built in locking support, and it's turned on by default. If you want to be safe, call SQLiteOpenDatabase.setLockingEnabled(true).

As for access to the shared preferences, I would encapsulate all access to SharedPreferences (read and write) in small functions that all use synchronized. (Be sure that they are atomic).

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for responding. So, I shouldn't worry about multiple threads with SQLite? For instance, thread 1 will just wait for thread 2 to finish if both are editing the database because file locking is built-in? If so, why do methods "isDbLockedByOtherThreads()" and "isDbLockedByCurrentThread()" exist? As for SharedPreferences, I'll add synchronized to that code segment per your recommendation.Thanks.
From the docs, setLockingEnabled() is used to "Control whether or not the SQLiteDatabase is made thread-safe by using locks around critical sections.". That implies that the OS does everything for you. (Btw, in general, I would never poll a lock like you did above - if you really have to synchronize something yourself, just create an Object and use notify/wait on it. Polls are typically a guarantee for sadness. Spinlocks should only ever be used in few cases where it makes sense.
Ok, that makes sense. I've seen examples where dummy objects were used as the monitor in the synchronized block, but do I need to do that here? Is my proposed change in the edit above the better way of doing this? Thanks.
synchronized(myDatabase) already locks the database object, so you don't need to do any further synchronization. This assumes that you only have one database object. If not, create a dummy lock object and use that instead. synchronized(lockObject) { everythingInHereIsAtomic; }. But agin, if setLockingEnabled() is set, you don't need to do anything at all in the specific case of SQLiteDatabase (I suppose your example now refers to the SharedPreferences object).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.