views:

64

answers:

1

Hello,

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  A: 

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).

EboMike
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.
borg17of20
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.
EboMike
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.
borg17of20
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).
EboMike
Ok, I changed the edit section above to just show the synchronized block, and I set the setLockingEnabled(true). I should be set?
borg17of20
Yep, that should do!
EboMike
Excellent, thank you.
borg17of20