虽然flutter主程序是单线程,不需要锁,但是async/await在使用不当的情况下还是会导致数据不同步甚至出错,
比如下面这个例子:
List<int>_t1 = List<int>();
justWait({@required int numberOfSeconds}) async {
await Future.delayed(Duration(seconds: numberOfSeconds));
}
test2() async {
await justWait(numberOfSeconds: 3);
_t1.clear();
}
test1() async {
for (var k in _t1) {
print("t1: $k");
await justWait(numberOfSeconds: 1);
}
_t1.clear();
}
test() {
print('=============================>');
for (var i = 0; i < 10; i++ ) {
_t1.add(i);
}
test1();
test2();
Future.delayed(Duration(seconds: 15), ()=> print(_t1));
}
输出结果:
flutter: t1: 1
flutter: t1: 2
[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: Concurrent modification during iteration: Instance(length:0) of '_GrowableList'.
#0 ListIterator.moveNext (dart:_internal/iterable.dart:337:7)
#1 Setting.test1 (package:xxx.dart:38:19)
<asynchronous suspension>
#2 Setting.test (package:xxx:62:5)
<asynchronous suspension>
... (一堆错误信息)
flutter: []
justWait
用来模拟一些长时间操作,当然实际中此处代码可能运行只有几十上百毫秒,这里故意把等待时间设为秒级是为了让问题更容易显现。
这里的问题是:在test1()方法中循环遍历_t1列表,但是循环中使用了await,此时如果在test2()中同样对_t1列表做了增加或者删除操作,会导致test1循环迭代出错,因为虽然是单线程,但是await会暂时挂起,等待操作完成后才继续,而此时test2中已经把列表清空了,所以会出现上面的问题。
这儿只是异步可能出错的一个简单例子,其实多个异步对资源的同时访问可能还会有很多情况,所以在使用异步时需要考虑清楚可能出现的情况。
网友评论