Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper use of yieldIfContendedSafely() in an Android Multithreaded Application

In my application, I am using an AsyncTask to write some data to a database in a transaction. This database is also accessed from the UI thread. While looking through the available database methods, I came across yieldIfContendedSafely(). It seems like this method should be used for any cases where a transaction is being made from a separate thread. But there is hardly any documentation on this method other than the following:

Temporarily end the transaction to let other threads run. The transaction is assumed to be successful so far. Do not call setTransactionSuccessful before calling this. When this returns a new transaction will have been created but not marked as successful. This assumes that there are no nested transactions (beginTransaction has only been called once) and will throw an exception if that is not the case.

Here is how I would assume that you would use this method from a thread:

        try {
        db.beginTransaction();
        //insert some stuff into the database here 
        ...



        // is this how you use this method?
        boolean yielded = db.yieldIfContendedSafely();
        if (yielded) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }



        db.setTransactionSuccessful();
    } catch (SQLException e) {
        return false;
    } finally {
        db.endTransaction();
        db.close();
    }

Is this the correct way to use this method? Is it alright to use db.yieldIfContendedSafely() more than once in the same transaction, in between multiple writes to different tables in the database? Any suggestions?

like image 795
James Avatar asked Feb 18 '11 02:02

James


1 Answers

Pulling some example code from the Android libraries it seems much simpler to use than that...

This is taken from com.android.providers.calendar.SQLiteContentProvider.java

@Override
public int bulkInsert(Uri uri, ContentValues[] values) {
    int numValues = values.length;
    mDb = mOpenHelper.getWritableDatabase();
    mDb.beginTransactionWithListener(this);
    try {
        for (int i = 0; i < numValues; i++) {
            Uri result = insertInTransaction(uri, values[i]);
            if (result != null) {
                mNotifyChange = true;
            }
            mDb.yieldIfContendedSafely();
        }
        mDb.setTransactionSuccessful();
    } finally {
        mDb.endTransaction();
    }

    onEndTransaction();
    return numValues;
}

Also looking into the source code for the function itself, it seems that, if yielded, the call will defer execution of your thread for a short period in any case.

like image 162
karora Avatar answered Jan 02 '23 13:01

karora