本文集中讨论一下Android基于ContentProvider的数据库体系的线程安全问题。ContentProivider是Android诞生之初就存在的四大组件之一,提供跨进程的数据共享机制。

一个应用的数据库体系一般分为三层:
(1)ContentProvider层。向系统注册的一个公开的数据访问接口,跨进程。将对于数据的操作(譬如增删改查)抽象出来。数据本身并不一定是数据库,可以接任何形式的数据源。本文只讨论数据库。
(2)SQLiteDatabase/SQLiteOpenHelper层。Android提供的访问SQLite数据库的框架层接口。作为一个移动OS,Android集成了SQLite数据库。ContentProvider如果使用了数据库,一般需要借助SQLiteDatabase/SQLiteOpenHelper与底层数据库交互。
(3)SQLite数据库。Android native层集成了SQLite作为外部库。代码位于external/sqlite。一个SQLite数据库对应一个.db文件。

对于(3),应用开发不直接打交道。本文主要讨论(1)(2)的线程安全问题。

1.ContentProvider线程/进程安全

ContentProvider的意义在于向其他应用提供数据访问接口。所以ContentProvider的线程安全是跨进程的。那么需要回答两个问题:
当多个应用中的多个线程同时通过注册在系统的某个Provider访问数据的时候,
(1)这些Provider是否同一个实例?
(2)这些对数据库的访问操作在数据提供方的进程中,是并行还是串行?如果是并行,访问操作是原子的吗?

先用三个app工程来实验。测试环境Android6.0.1。

工程1:Provider方

ContentProvider代码

public class TestProvider extends ContentProvider {    @Override    public boolean onCreate() {        return true;    }    @Nullable    @Override    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {        Log.i("TEST_PROVIDER", "query() : " + uri + '\n' +                "          provider : "  + this + '\n' +                "          thread id : " + Thread.currentThread().getId() + '\n' +                "          thread name : " + Thread.currentThread().getName() + '\n' +                "          thread : " + Thread.currentThread() + '\n' +                "          process tid : " + Process.myTid() + '\n' +                "          process uid : " + Process.myUid() + '\n' +                "          process pid : " + Process.myPid() + '\n' +                "          calling uid : " + Binder.getCallingUid() + '\n' +                "          calling pid : " + Binder.getCallingPid());        try {            Thread.sleep(300);        } catch (InterruptedException e) {            e.printStackTrace();        }        return null;    }    @Nullable    @Override    public String getType(@NonNull Uri uri) {        return null;    }    @Nullable    @Override    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {        return null;    }    @Override    public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {        return 0;    }    @Override    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {        return 0;    }}

Manifest文件中Provider的声明

        <provider            android:authorities="com.android.testproviderauthority"            android:name=".TestProvider"            android:exported="true"/>

这个Provider极其简单,没有挂载任何的数据,只是在query方法中Log出我们关心的运行时信息。

工程2:Provider使用方1

    private void test() {        for (int i = 0 ; i < 100 ; i++) {            final int ii = i;            new Thread() {                public void run() {                    testQuery(ii);                }            }.start();        }    }    private void testQuery(int i) {        Uri uri = Uri.parse("content://com.android.testproviderauthority");        Uri.Builder builder = uri.buildUpon();        builder.appendPath("TEST_QUERY_ONE_" + i);        Cursor cursor = getContentResolver().query(builder.build(), null, null, null, null);        if (cursor == null) {            Log.i("TEST_QUERY_1", Thread.currentThread().getId() + " , cursor null");        } else {            Log.i("TEST_QUERY_1",  Thread.currentThread().getId() + " , cursor count - " + cursor.getCount());        }    }

100个线程同时去query工程1的数据。

工程3:Provider使用方2

    private void test() {        for (int i = 0 ; i < 100 ; i++) {            final int ii = i;            new Thread() {                public void run() {                    testQuery(ii);                }            }.start();        }    }    private void testQuery(int i) {        Uri uri = Uri.parse("content://com.android.testproviderauthority");        Uri.Builder builder = uri.buildUpon();        builder.appendPath("TEST_QUERY_TWO_" + i);        Cursor cursor = getContentResolver().query(builder.build(), null, null, null, null);        if (cursor == null) {            Log.i("TEST_QUERY_2", Thread.currentThread().getId() + " , cursor null");        } else {            Log.i("TEST_QUERY_2",  Thread.currentThread().getId() + " , cursor count - " + cursor.getCount());        }    }

工程2测试log:

10-27 15:23:07.408  6668  6698 I TEST_PROVIDER: query() : content://com.android.testproviderauthority/TEST_QUERY_ONE_9610-27 15:23:07.408  6668  6698 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@9510e210-27 15:23:07.408  6668  6698 I TEST_PROVIDER:           thread id : 42510-27 15:23:07.408  6668  6698 I TEST_PROVIDER:           thread name : Binder:6668_310-27 15:23:07.408  6668  6698 I TEST_PROVIDER:           thread : Thread[Binder:6668_3,5,main]10-27 15:23:07.408  6668  6698 I TEST_PROVIDER:           process tid : 669810-27 15:23:07.408  6668  6698 I TEST_PROVIDER:           process uid : 1013510-27 15:23:07.408  6668  6698 I TEST_PROVIDER:           process pid : 666810-27 15:23:07.408  6668  6698 I TEST_PROVIDER:           calling uid : 1012910-27 15:23:07.408  6668  6698 I TEST_PROVIDER:           calling pid : 535410-27 15:23:07.408  6668  6679 I TEST_PROVIDER: query() : content://com.android.testproviderauthority/TEST_QUERY_ONE_9710-27 15:23:07.408  6668  6679 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@9510e210-27 15:23:07.408  6668  6679 I TEST_PROVIDER:           thread id : 41710-27 15:23:07.408  6668  6679 I TEST_PROVIDER:           thread name : Binder:6668_110-27 15:23:07.408  6668  6679 I TEST_PROVIDER:           thread : Thread[Binder:6668_1,5,main]10-27 15:23:07.408  6668  6679 I TEST_PROVIDER:           process tid : 667910-27 15:23:07.408  6668  6679 I TEST_PROVIDER:           process uid : 1013510-27 15:23:07.408  6668  6679 I TEST_PROVIDER:           process pid : 666810-27 15:23:07.408  6668  6679 I TEST_PROVIDER:           calling uid : 1012910-27 15:23:07.408  6668  6679 I TEST_PROVIDER:           calling pid : 535410-27 15:23:07.409  6668  6680 I TEST_PROVIDER: query() : content://com.android.testproviderauthority/TEST_QUERY_ONE_9910-27 15:23:07.409  6668  6680 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@9510e210-27 15:23:07.409  6668  6680 I TEST_PROVIDER:           thread id : 41810-27 15:23:07.409  6668  6680 I TEST_PROVIDER:           thread name : Binder:6668_210-27 15:23:07.409  6668  6680 I TEST_PROVIDER:           thread : Thread[Binder:6668_2,5,main]10-27 15:23:07.409  6668  6680 I TEST_PROVIDER:           process tid : 668010-27 15:23:07.409  6668  6680 I TEST_PROVIDER:           process uid : 1013510-27 15:23:07.409  6668  6680 I TEST_PROVIDER:           process pid : 666810-27 15:23:07.409  6668  6680 I TEST_PROVIDER:           calling uid : 1012910-27 15:23:07.409  6668  6680 I TEST_PROVIDER:           calling pid : 535410-27 15:23:07.409  6668  6759 I TEST_PROVIDER: query() : content://com.android.testproviderauthority/TEST_QUERY_ONE_9810-27 15:23:07.409  6668  6759 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@9510e210-27 15:23:07.409  6668  6759 I TEST_PROVIDER:           thread id : 42710-27 15:23:07.409  6668  6759 I TEST_PROVIDER:           thread name : Binder:6668_410-27 15:23:07.409  6668  6759 I TEST_PROVIDER:           thread : Thread[Binder:6668_4,5,main]10-27 15:23:07.409  6668  6759 I TEST_PROVIDER:           process tid : 675910-27 15:23:07.409  6668  6759 I TEST_PROVIDER:           process uid : 1013510-27 15:23:07.409  6668  6759 I TEST_PROVIDER:           process pid : 666810-27 15:23:07.409  6668  6759 I TEST_PROVIDER:           calling uid : 1012910-27 15:23:07.409  6668  6759 I TEST_PROVIDER:           calling pid : 5354

工程3测试log:

10-27 15:23:39.187  6668  6773 I TEST_PROVIDER: query() : content://com.android.testproviderauthority/TEST_QUERY_TWO_9710-27 15:23:39.187  6668  6773 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@9510e210-27 15:23:39.187  6668  6773 I TEST_PROVIDER:           thread id : 43410-27 15:23:39.187  6668  6773 I TEST_PROVIDER:           thread name : Binder:6668_B10-27 15:23:39.187  6668  6773 I TEST_PROVIDER:           thread : Thread[Binder:6668_B,5,main]10-27 15:23:39.187  6668  6773 I TEST_PROVIDER:           process tid : 677310-27 15:23:39.187  6668  6773 I TEST_PROVIDER:           process uid : 1013510-27 15:23:39.187  6668  6773 I TEST_PROVIDER:           process pid : 666810-27 15:23:39.187  6668  6773 I TEST_PROVIDER:           calling uid : 1013410-27 15:23:39.187  6668  6773 I TEST_PROVIDER:           calling pid : 551110-27 15:23:39.187  6668  6772 I TEST_PROVIDER: query() : content://com.android.testproviderauthority/TEST_QUERY_TWO_9910-27 15:23:39.187  6668  6772 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@9510e210-27 15:23:39.187  6668  6772 I TEST_PROVIDER:           thread id : 43310-27 15:23:39.187  6668  6772 I TEST_PROVIDER:           thread name : Binder:6668_A10-27 15:23:39.187  6668  6772 I TEST_PROVIDER:           thread : Thread[Binder:6668_A,5,main]10-27 15:23:39.187  6668  6772 I TEST_PROVIDER:           process tid : 677210-27 15:23:39.187  6668  6772 I TEST_PROVIDER:           process uid : 1013510-27 15:23:39.187  6668  6772 I TEST_PROVIDER:           process pid : 666810-27 15:23:39.187  6668  6772 I TEST_PROVIDER:           calling uid : 1013410-27 15:23:39.187  6668  6772 I TEST_PROVIDER:           calling pid : 551110-27 15:23:39.187  6668  6768 I TEST_PROVIDER: query() : content://com.android.testproviderauthority/TEST_QUERY_TWO_9810-27 15:23:39.187  6668  6768 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@9510e210-27 15:23:39.187  6668  6768 I TEST_PROVIDER:           thread id : 43110-27 15:23:39.187  6668  6768 I TEST_PROVIDER:           thread name : Binder:6668_810-27 15:23:39.187  6668  6768 I TEST_PROVIDER:           thread : Thread[Binder:6668_8,5,main]10-27 15:23:39.187  6668  6768 I TEST_PROVIDER:           process tid : 676810-27 15:23:39.187  6668  6768 I TEST_PROVIDER:           process uid : 1013510-27 15:23:39.187  6668  6768 I TEST_PROVIDER:           process pid : 666810-27 15:23:39.187  6668  6768 I TEST_PROVIDER:           calling uid : 1013410-27 15:23:39.187  6668  6768 I TEST_PROVIDER:           calling pid : 551110-27 15:23:39.189  6668  6766 I TEST_PROVIDER: query() : content://com.android.testproviderauthority/TEST_QUERY_TWO_9610-27 15:23:39.189  6668  6766 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@9510e210-27 15:23:39.189  6668  6766 I TEST_PROVIDER:           thread id : 43010-27 15:23:39.189  6668  6766 I TEST_PROVIDER:           thread name : Binder:6668_710-27 15:23:39.189  6668  6766 I TEST_PROVIDER:           thread : Thread[Binder:6668_7,5,main]10-27 15:23:39.189  6668  6766 I TEST_PROVIDER:           process tid : 676610-27 15:23:39.189  6668  6766 I TEST_PROVIDER:           process uid : 1013510-27 15:23:39.189  6668  6766 I TEST_PROVIDER:           process pid : 666810-27 15:23:39.189  6668  6766 I TEST_PROVIDER:           calling uid : 1013410-27 15:23:39.189  6668  6766 I TEST_PROVIDER:           calling pid : 5511

从上面代码和log可以看到:
(1)不管Provider使用方是同一个进程的不同线程,还是不同的进程,Provider方实际上是同一个Provider对象实例。(当然,如果Provider方进程重启了,或者Provider本身或者Binder出现问题重启了,那另当别论,不是这里讨论的范围。)
(2)并发访问时,Provider方query()方法运行在不同的线程,实际上是运行在Provider方的进程的Binder线程池中。
还剩一个问题,query()是原子的吗?继续实验。将Provider的query()方法做一下改动:

    @Nullable    @Override    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {        Log.i("TEST_PROVIDER", "query() START: " + uri + '\n' +                "          provider : "  + this + '\n' +                "          thread id : " + Thread.currentThread().getId() + '\n' +                "          thread name : " + Thread.currentThread().getName() + '\n' +                "          thread : " + Thread.currentThread() + '\n' +                "          process tid : " + Process.myTid() + '\n' +                "          process uid : " + Process.myUid() + '\n' +                "          process pid : " + Process.myPid() + '\n' +                "          calling uid : " + Binder.getCallingUid() + '\n' +                "          calling pid : " + Binder.getCallingPid());        try {            Thread.sleep(3000);        } catch (InterruptedException e) {            e.printStackTrace();        }        Log.i("TEST_PROVIDER", "query() FINISH: " + uri + '\n' +                "          provider : "  + this + '\n' +                "          thread id : " + Thread.currentThread().getId() + '\n' +                "          thread name : " + Thread.currentThread().getName() + '\n' +                "          thread : " + Thread.currentThread() + '\n' +                "          process tid : " + Process.myTid() + '\n' +                "          process uid : " + Process.myUid() + '\n' +                "          process pid : " + Process.myPid() + '\n' +                "          calling uid : " + Binder.getCallingUid() + '\n' +                "          calling pid : " + Binder.getCallingPid());        return null;    }

sleep时间增加到3s,并且在返回前也打一条log。
在工程2中访问数据,把并行访问线程数降低到5:

    private void test() {        for (int i = 0 ; i < 5 ; i++) {            final int ii = i;            new Thread() {                public void run() {                    testQuery(ii);                }            }.start();        }    }

结果log:

10-27 15:44:04.924  7311  7339 I TEST_PROVIDER: query() START: content://com.android.testproviderauthority/TEST_QUERY_ONE_010-27 15:44:04.924  7311  7339 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:44:04.924  7311  7339 I TEST_PROVIDER:           thread id : 43310-27 15:44:04.924  7311  7339 I TEST_PROVIDER:           thread name : Binder:7311_310-27 15:44:04.924  7311  7339 I TEST_PROVIDER:           thread : Thread[Binder:7311_3,5,main]10-27 15:44:04.924  7311  7339 I TEST_PROVIDER:           process tid : 733910-27 15:44:04.924  7311  7339 I TEST_PROVIDER:           process uid : 1013510-27 15:44:04.924  7311  7339 I TEST_PROVIDER:           process pid : 731110-27 15:44:04.924  7311  7339 I TEST_PROVIDER:           calling uid : 1012910-27 15:44:04.924  7311  7339 I TEST_PROVIDER:           calling pid : 721310-27 15:44:04.926  7311  7323 I TEST_PROVIDER: query() START: content://com.android.testproviderauthority/TEST_QUERY_ONE_110-27 15:44:04.926  7311  7323 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:44:04.926  7311  7323 I TEST_PROVIDER:           thread id : 42610-27 15:44:04.926  7311  7323 I TEST_PROVIDER:           thread name : Binder:7311_210-27 15:44:04.926  7311  7323 I TEST_PROVIDER:           thread : Thread[Binder:7311_2,5,main]10-27 15:44:04.926  7311  7323 I TEST_PROVIDER:           process tid : 732310-27 15:44:04.926  7311  7323 I TEST_PROVIDER:           process uid : 1013510-27 15:44:04.926  7311  7323 I TEST_PROVIDER:           process pid : 731110-27 15:44:04.926  7311  7323 I TEST_PROVIDER:           calling uid : 1012910-27 15:44:04.926  7311  7323 I TEST_PROVIDER:           calling pid : 721310-27 15:44:04.927  7311  7322 I TEST_PROVIDER: query() START: content://com.android.testproviderauthority/TEST_QUERY_ONE_210-27 15:44:04.927  7311  7322 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:44:04.927  7311  7322 I TEST_PROVIDER:           thread id : 42510-27 15:44:04.927  7311  7322 I TEST_PROVIDER:           thread name : Binder:7311_110-27 15:44:04.927  7311  7322 I TEST_PROVIDER:           thread : Thread[Binder:7311_1,5,main]10-27 15:44:04.927  7311  7322 I TEST_PROVIDER:           process tid : 732210-27 15:44:04.927  7311  7322 I TEST_PROVIDER:           process uid : 1013510-27 15:44:04.927  7311  7322 I TEST_PROVIDER:           process pid : 731110-27 15:44:04.927  7311  7322 I TEST_PROVIDER:           calling uid : 1012910-27 15:44:04.927  7311  7322 I TEST_PROVIDER:           calling pid : 721310-27 15:44:04.929  7311  7376 I TEST_PROVIDER: query() START: content://com.android.testproviderauthority/TEST_QUERY_ONE_410-27 15:44:04.929  7311  7376 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:44:04.929  7311  7376 I TEST_PROVIDER:           thread id : 43410-27 15:44:04.929  7311  7376 I TEST_PROVIDER:           thread name : Binder:7311_410-27 15:44:04.929  7311  7376 I TEST_PROVIDER:           thread : Thread[Binder:7311_4,5,main]10-27 15:44:04.929  7311  7376 I TEST_PROVIDER:           process tid : 737610-27 15:44:04.929  7311  7376 I TEST_PROVIDER:           process uid : 1013510-27 15:44:04.929  7311  7376 I TEST_PROVIDER:           process pid : 731110-27 15:44:04.929  7311  7376 I TEST_PROVIDER:           calling uid : 1012910-27 15:44:04.929  7311  7376 I TEST_PROVIDER:           calling pid : 721310-27 15:44:04.932  7311  7377 I TEST_PROVIDER: query() START: content://com.android.testproviderauthority/TEST_QUERY_ONE_310-27 15:44:04.932  7311  7377 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:44:04.932  7311  7377 I TEST_PROVIDER:           thread id : 43510-27 15:44:04.932  7311  7377 I TEST_PROVIDER:           thread name : Binder:7311_510-27 15:44:04.932  7311  7377 I TEST_PROVIDER:           thread : Thread[Binder:7311_5,5,main]10-27 15:44:04.932  7311  7377 I TEST_PROVIDER:           process tid : 737710-27 15:44:04.932  7311  7377 I TEST_PROVIDER:           process uid : 1013510-27 15:44:04.932  7311  7377 I TEST_PROVIDER:           process pid : 731110-27 15:44:04.932  7311  7377 I TEST_PROVIDER:           calling uid : 1012910-27 15:44:04.932  7311  7377 I TEST_PROVIDER:           calling pid : 721310-27 15:44:07.925  7311  7339 I TEST_PROVIDER: query() FINISH: content://com.android.testproviderauthority/TEST_QUERY_ONE_010-27 15:44:07.925  7311  7339 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:44:07.925  7311  7339 I TEST_PROVIDER:           thread id : 43310-27 15:44:07.925  7311  7339 I TEST_PROVIDER:           thread name : Binder:7311_310-27 15:44:07.925  7311  7339 I TEST_PROVIDER:           thread : Thread[Binder:7311_3,5,main]10-27 15:44:07.925  7311  7339 I TEST_PROVIDER:           process tid : 733910-27 15:44:07.925  7311  7339 I TEST_PROVIDER:           process uid : 1013510-27 15:44:07.925  7311  7339 I TEST_PROVIDER:           process pid : 731110-27 15:44:07.925  7311  7339 I TEST_PROVIDER:           calling uid : 1012910-27 15:44:07.925  7311  7339 I TEST_PROVIDER:           calling pid : 721310-27 15:44:07.926  7311  7323 I TEST_PROVIDER: query() FINISH: content://com.android.testproviderauthority/TEST_QUERY_ONE_110-27 15:44:07.926  7311  7323 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:44:07.926  7311  7323 I TEST_PROVIDER:           thread id : 42610-27 15:44:07.926  7311  7323 I TEST_PROVIDER:           thread name : Binder:7311_210-27 15:44:07.926  7311  7323 I TEST_PROVIDER:           thread : Thread[Binder:7311_2,5,main]10-27 15:44:07.926  7311  7323 I TEST_PROVIDER:           process tid : 732310-27 15:44:07.926  7311  7323 I TEST_PROVIDER:           process uid : 1013510-27 15:44:07.926  7311  7323 I TEST_PROVIDER:           process pid : 731110-27 15:44:07.926  7311  7323 I TEST_PROVIDER:           calling uid : 1012910-27 15:44:07.926  7311  7323 I TEST_PROVIDER:           calling pid : 721310-27 15:44:07.927  7311  7322 I TEST_PROVIDER: query() FINISH: content://com.android.testproviderauthority/TEST_QUERY_ONE_210-27 15:44:07.927  7311  7322 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:44:07.927  7311  7322 I TEST_PROVIDER:           thread id : 42510-27 15:44:07.927  7311  7322 I TEST_PROVIDER:           thread name : Binder:7311_110-27 15:44:07.927  7311  7322 I TEST_PROVIDER:           thread : Thread[Binder:7311_1,5,main]10-27 15:44:07.927  7311  7322 I TEST_PROVIDER:           process tid : 732210-27 15:44:07.927  7311  7322 I TEST_PROVIDER:           process uid : 1013510-27 15:44:07.927  7311  7322 I TEST_PROVIDER:           process pid : 731110-27 15:44:07.927  7311  7322 I TEST_PROVIDER:           calling uid : 1012910-27 15:44:07.927  7311  7322 I TEST_PROVIDER:           calling pid : 721310-27 15:44:07.930  7311  7376 I TEST_PROVIDER: query() FINISH: content://com.android.testproviderauthority/TEST_QUERY_ONE_410-27 15:44:07.930  7311  7376 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:44:07.930  7311  7376 I TEST_PROVIDER:           thread id : 43410-27 15:44:07.930  7311  7376 I TEST_PROVIDER:           thread name : Binder:7311_410-27 15:44:07.930  7311  7376 I TEST_PROVIDER:           thread : Thread[Binder:7311_4,5,main]10-27 15:44:07.930  7311  7376 I TEST_PROVIDER:           process tid : 737610-27 15:44:07.930  7311  7376 I TEST_PROVIDER:           process uid : 1013510-27 15:44:07.930  7311  7376 I TEST_PROVIDER:           process pid : 731110-27 15:44:07.930  7311  7376 I TEST_PROVIDER:           calling uid : 1012910-27 15:44:07.930  7311  7376 I TEST_PROVIDER:           calling pid : 721310-27 15:44:07.933  7311  7377 I TEST_PROVIDER: query() FINISH: content://com.android.testproviderauthority/TEST_QUERY_ONE_310-27 15:44:07.933  7311  7377 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:44:07.933  7311  7377 I TEST_PROVIDER:           thread id : 43510-27 15:44:07.933  7311  7377 I TEST_PROVIDER:           thread name : Binder:7311_510-27 15:44:07.933  7311  7377 I TEST_PROVIDER:           thread : Thread[Binder:7311_5,5,main]10-27 15:44:07.933  7311  7377 I TEST_PROVIDER:           process tid : 737710-27 15:44:07.933  7311  7377 I TEST_PROVIDER:           process uid : 1013510-27 15:44:07.933  7311  7377 I TEST_PROVIDER:           process pid : 731110-27 15:44:07.933  7311  7377 I TEST_PROVIDER:           calling uid : 1012910-27 15:44:07.933  7311  7377 I TEST_PROVIDER:           calling pid : 7213

显然,看到不是原子操作。Android框架层并没有做什么以使数据操作原子化。
手动给query()方法添加synchronized关键字之后测试,得到原子化的结果。log:

10-27 15:48:00.111  7483  7512 I TEST_PROVIDER: query() START: content://com.android.testproviderauthority/TEST_QUERY_ONE_310-27 15:48:00.111  7483  7512 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:48:00.111  7483  7512 I TEST_PROVIDER:           thread id : 43810-27 15:48:00.111  7483  7512 I TEST_PROVIDER:           thread name : Binder:7483_310-27 15:48:00.111  7483  7512 I TEST_PROVIDER:           thread : Thread[Binder:7483_3,5,main]10-27 15:48:00.111  7483  7512 I TEST_PROVIDER:           process tid : 751210-27 15:48:00.111  7483  7512 I TEST_PROVIDER:           process uid : 1013510-27 15:48:00.111  7483  7512 I TEST_PROVIDER:           process pid : 748310-27 15:48:00.111  7483  7512 I TEST_PROVIDER:           calling uid : 1012910-27 15:48:00.111  7483  7512 I TEST_PROVIDER:           calling pid : 721310-27 15:48:03.113  7483  7512 I TEST_PROVIDER: query() FINISH: content://com.android.testproviderauthority/TEST_QUERY_ONE_310-27 15:48:03.113  7483  7512 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:48:03.113  7483  7512 I TEST_PROVIDER:           thread id : 43810-27 15:48:03.113  7483  7512 I TEST_PROVIDER:           thread name : Binder:7483_310-27 15:48:03.113  7483  7512 I TEST_PROVIDER:           thread : Thread[Binder:7483_3,5,main]10-27 15:48:03.113  7483  7512 I TEST_PROVIDER:           process tid : 751210-27 15:48:03.113  7483  7512 I TEST_PROVIDER:           process uid : 1013510-27 15:48:03.113  7483  7512 I TEST_PROVIDER:           process pid : 748310-27 15:48:03.113  7483  7512 I TEST_PROVIDER:           calling uid : 1012910-27 15:48:03.113  7483  7512 I TEST_PROVIDER:           calling pid : 721310-27 15:48:03.113  7483  7495 I TEST_PROVIDER: query() START: content://com.android.testproviderauthority/TEST_QUERY_ONE_010-27 15:48:03.113  7483  7495 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:48:03.113  7483  7495 I TEST_PROVIDER:           thread id : 43010-27 15:48:03.113  7483  7495 I TEST_PROVIDER:           thread name : Binder:7483_210-27 15:48:03.113  7483  7495 I TEST_PROVIDER:           thread : Thread[Binder:7483_2,5,main]10-27 15:48:03.113  7483  7495 I TEST_PROVIDER:           process tid : 749510-27 15:48:03.113  7483  7495 I TEST_PROVIDER:           process uid : 1013510-27 15:48:03.113  7483  7495 I TEST_PROVIDER:           process pid : 748310-27 15:48:03.113  7483  7495 I TEST_PROVIDER:           calling uid : 1012910-27 15:48:03.113  7483  7495 I TEST_PROVIDER:           calling pid : 721310-27 15:48:06.115  7483  7495 I TEST_PROVIDER: query() FINISH: content://com.android.testproviderauthority/TEST_QUERY_ONE_010-27 15:48:06.115  7483  7495 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:48:06.115  7483  7495 I TEST_PROVIDER:           thread id : 43010-27 15:48:06.115  7483  7495 I TEST_PROVIDER:           thread name : Binder:7483_210-27 15:48:06.115  7483  7495 I TEST_PROVIDER:           thread : Thread[Binder:7483_2,5,main]10-27 15:48:06.115  7483  7495 I TEST_PROVIDER:           process tid : 749510-27 15:48:06.115  7483  7495 I TEST_PROVIDER:           process uid : 1013510-27 15:48:06.115  7483  7495 I TEST_PROVIDER:           process pid : 748310-27 15:48:06.115  7483  7495 I TEST_PROVIDER:           calling uid : 1012910-27 15:48:06.115  7483  7495 I TEST_PROVIDER:           calling pid : 721310-27 15:48:06.115  7483  7494 I TEST_PROVIDER: query() START: content://com.android.testproviderauthority/TEST_QUERY_ONE_110-27 15:48:06.115  7483  7494 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:48:06.115  7483  7494 I TEST_PROVIDER:           thread id : 42910-27 15:48:06.115  7483  7494 I TEST_PROVIDER:           thread name : Binder:7483_110-27 15:48:06.115  7483  7494 I TEST_PROVIDER:           thread : Thread[Binder:7483_1,5,main]10-27 15:48:06.115  7483  7494 I TEST_PROVIDER:           process tid : 749410-27 15:48:06.115  7483  7494 I TEST_PROVIDER:           process uid : 1013510-27 15:48:06.115  7483  7494 I TEST_PROVIDER:           process pid : 748310-27 15:48:06.115  7483  7494 I TEST_PROVIDER:           calling uid : 1012910-27 15:48:06.115  7483  7494 I TEST_PROVIDER:           calling pid : 721310-27 15:48:09.116  7483  7494 I TEST_PROVIDER: query() FINISH: content://com.android.testproviderauthority/TEST_QUERY_ONE_110-27 15:48:09.116  7483  7494 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:48:09.116  7483  7494 I TEST_PROVIDER:           thread id : 42910-27 15:48:09.116  7483  7494 I TEST_PROVIDER:           thread name : Binder:7483_110-27 15:48:09.116  7483  7494 I TEST_PROVIDER:           thread : Thread[Binder:7483_1,5,main]10-27 15:48:09.116  7483  7494 I TEST_PROVIDER:           process tid : 749410-27 15:48:09.116  7483  7494 I TEST_PROVIDER:           process uid : 1013510-27 15:48:09.116  7483  7494 I TEST_PROVIDER:           process pid : 748310-27 15:48:09.116  7483  7494 I TEST_PROVIDER:           calling uid : 1012910-27 15:48:09.116  7483  7494 I TEST_PROVIDER:           calling pid : 721310-27 15:48:09.117  7483  7542 I TEST_PROVIDER: query() START: content://com.android.testproviderauthority/TEST_QUERY_ONE_410-27 15:48:09.117  7483  7542 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:48:09.117  7483  7542 I TEST_PROVIDER:           thread id : 44010-27 15:48:09.117  7483  7542 I TEST_PROVIDER:           thread name : Binder:7483_510-27 15:48:09.117  7483  7542 I TEST_PROVIDER:           thread : Thread[Binder:7483_5,5,main]10-27 15:48:09.117  7483  7542 I TEST_PROVIDER:           process tid : 754210-27 15:48:09.117  7483  7542 I TEST_PROVIDER:           process uid : 1013510-27 15:48:09.117  7483  7542 I TEST_PROVIDER:           process pid : 748310-27 15:48:09.117  7483  7542 I TEST_PROVIDER:           calling uid : 1012910-27 15:48:09.117  7483  7542 I TEST_PROVIDER:           calling pid : 721310-27 15:48:12.118  7483  7542 I TEST_PROVIDER: query() FINISH: content://com.android.testproviderauthority/TEST_QUERY_ONE_410-27 15:48:12.118  7483  7542 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:48:12.118  7483  7542 I TEST_PROVIDER:           thread id : 44010-27 15:48:12.118  7483  7542 I TEST_PROVIDER:           thread name : Binder:7483_510-27 15:48:12.118  7483  7542 I TEST_PROVIDER:           thread : Thread[Binder:7483_5,5,main]10-27 15:48:12.118  7483  7542 I TEST_PROVIDER:           process tid : 754210-27 15:48:12.118  7483  7542 I TEST_PROVIDER:           process uid : 1013510-27 15:48:12.118  7483  7542 I TEST_PROVIDER:           process pid : 748310-27 15:48:12.118  7483  7542 I TEST_PROVIDER:           calling uid : 1012910-27 15:48:12.118  7483  7542 I TEST_PROVIDER:           calling pid : 721310-27 15:48:12.119  7483  7541 I TEST_PROVIDER: query() START: content://com.android.testproviderauthority/TEST_QUERY_ONE_210-27 15:48:12.119  7483  7541 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:48:12.119  7483  7541 I TEST_PROVIDER:           thread id : 43910-27 15:48:12.119  7483  7541 I TEST_PROVIDER:           thread name : Binder:7483_410-27 15:48:12.119  7483  7541 I TEST_PROVIDER:           thread : Thread[Binder:7483_4,5,main]10-27 15:48:12.119  7483  7541 I TEST_PROVIDER:           process tid : 754110-27 15:48:12.119  7483  7541 I TEST_PROVIDER:           process uid : 1013510-27 15:48:12.119  7483  7541 I TEST_PROVIDER:           process pid : 748310-27 15:48:12.119  7483  7541 I TEST_PROVIDER:           calling uid : 1012910-27 15:48:12.119  7483  7541 I TEST_PROVIDER:           calling pid : 721310-27 15:48:15.119  7483  7541 I TEST_PROVIDER: query() FINISH: content://com.android.testproviderauthority/TEST_QUERY_ONE_210-27 15:48:15.119  7483  7541 I TEST_PROVIDER:           provider : com.example.testcontentprovider.TestProvider@e26aa1f10-27 15:48:15.119  7483  7541 I TEST_PROVIDER:           thread id : 43910-27 15:48:15.119  7483  7541 I TEST_PROVIDER:           thread name : Binder:7483_410-27 15:48:15.119  7483  7541 I TEST_PROVIDER:           thread : Thread[Binder:7483_4,5,main]10-27 15:48:15.119  7483  7541 I TEST_PROVIDER:           process tid : 754110-27 15:48:15.119  7483  7541 I TEST_PROVIDER:           process uid : 1013510-27 15:48:15.119  7483  7541 I TEST_PROVIDER:           process pid : 748310-27 15:48:15.119  7483  7541 I TEST_PROVIDER:           calling uid : 1012910-27 15:48:15.119  7483  7541 I TEST_PROVIDER:           calling pid : 7213

上述实验以最常用的query()方法为例分析。query()为读操作,另外实验了写操作update(),结果相同。

更多相关文章

  1. Android(安卓)IPC之Messenger和AIDL(android开发艺术探索随笔)
  2. 腾讯微博java(android) sdk 数据更新相关api详细介绍
  3. 安卓数据库sqlite增删查改—模拟用户登录与管理(2020-6-19)
  4. android SQLite实现本地登录注册功能,SQLite简单应用(android stu
  5. Android数据库的操作之存储和获取
  6. Android中EventBus原理及用法详情
  7. 什么是ANR,如何避免?
  8. 收藏老罗的----------Android应用程序组件Content Provider简要
  9. Android中非UI线程中不能操作UI线程的详解

随机推荐

  1. Android四大基本组件介绍与生命周期
  2. Artifactory 4 PRO /HA 版 搭建Android镜
  3. Activity中的四种启动模式
  4. android Activity 四大启动模式探究
  5. E/错误(3907): android.view.ViewRootImp
  6. Activity生命周期的回调,你应该知道得更多
  7. Android系统架构ABC
  8. mk中的 android:sharedUserId和LOCAL_CER
  9. Android(安卓)之 Notification
  10. Android(安卓)Menu