Android(安卓)ContentProvider的线程安全(一)
本文集中讨论一下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(),结果相同。
更多相关文章
- Android(安卓)IPC之Messenger和AIDL(android开发艺术探索随笔)
- 腾讯微博java(android) sdk 数据更新相关api详细介绍
- 安卓数据库sqlite增删查改—模拟用户登录与管理(2020-6-19)
- android SQLite实现本地登录注册功能,SQLite简单应用(android stu
- Android数据库的操作之存储和获取
- Android中EventBus原理及用法详情
- 什么是ANR,如何避免?
- 收藏老罗的----------Android应用程序组件Content Provider简要
- Android中非UI线程中不能操作UI线程的详解