问题
多线程下,修改tableview的数据源,数据同步问题的解决方案?应用场景:
在某些新闻类app中,当有用户做一些删除操作(比如关掉了一条广告),然后同时又有数据的后向刷新(loadMoreData)
删除操作是在主线程,loadMoreData是在子线程,这就涉及到了多线程对数据的访问中,怎么保证数据源同步问题。解决方案
- 并发访问,数据拷贝
我们来看一幅时序图
主线程对数据源1 进行了删除操作,得到数据源2;
子线程对数据源1 进行数据解析预排版等操作,得到数据源3;
最后主线程reload UI时,从子线程拿到的是数据源3,而数据源3里是含有被删除的哪一行数据的;
这就造成了被删除的数据又被刷出来的bug;
怎么解决呢?
在主线程对数据源1进行删除操作得到数据源2时,记录下删除操作;
子线程完成网络请求数据解析后,同步下删除操作,这样得到的数据源和2相同;
最后,主线程reload UI 时,数据源也是和2是一样的。
2. 串行访问
还有一种串行访问的解决方案:不管是子线程还是主线程,对tableView的数据源操作都提交到串行队列上,来避免数据源错乱问题。
子线程把 对数据源1的网络请求/数据解析等操作提交到 串行队列;
串行队列对新增数据进行预排版等操作;
主线程删除数据后,把删除操作异步提交到串行队列,waiting 串行队列完成同步数据操作(这里要注意是 【异步提交】);
最后等串行队列完成数据删除的同步,得到数据源2,返回给主线程reload UI。
这两种方案各有利弊:
- 并发访问,数据拷贝的解决方案,如果数据量较大,大量的数据拷贝会增加内存开销;
- 串行访问的方案,如果子线程任务耗时太久,会造成主线程延时;
在开发过程中,可以根据项目的实际应用场景来决定采用哪种方案。