flutter async/await异步的坑

2019-07-30  本文已影响0人  云上听风

虽然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中已经把列表清空了,所以会出现上面的问题。

这儿只是异步可能出错的一个简单例子,其实多个异步对资源的同时访问可能还会有很多情况,所以在使用异步时需要考虑清楚可能出现\color{red}{资源竞争以及时序错乱}的情况。

上一篇下一篇

猜你喜欢

热点阅读