Berdebar. Sinkronisasi dan paralelisme

Halo, Habr! Saya hadir untuk Anda terjemahan artikel "Futures - Isolates - Event Loop" oleh Didier Boelens tentang asinkron dan multithreading di Dart(dan Flutterkhususnya).


TLDR:  ,        .       Event Loop, Future  async/await (,  JavaScript),   otlin,  ,       . ,        .

Dan tentang terjemahan persyaratan. Dalam bahasa lisankita Saya mengatakan "stream", "perdagangan", "futures", dll, sementara di cetak istilah ini terlihat aneh dan canggung.


Pada saat yang sama, itu Streamadalah Stream, dan Thread- Stream. Konteks dalam hal ini tidak selalu menyimpan. Isolat yang sama, untuk seleraku, terdengar normal dalam bahasa Rusia, jadi di suatu tempat aku menggunakan ejaan dalam bahasa Cyrillic, dan di suatu tempat dalam bahasa aslinya.


Di sana-sini dalam kurung setelah kata-kata Rusia asli bahasa Inggris mereka, kadang-kadang sebaliknya.


pengantar


Baru-baru ini, saya sering mendapatkan pertanyaan yang berkaitan dengan konsep Future, async, await, Isolatedan eksekusi paralel kode.


Selain itu, beberapa pengembang memiliki masalah dalam memahami urutan eksekusi kode mereka.


Saya memutuskan untuk mengambil kesempatan dan mencurahkan artikel untuk masalah ini. Pada saat yang sama, saya akan mencoba untuk menghilangkan kebingungan terkait dengan konsep dan .


Dart - bahasa berulir tunggal


, DartFlutter Dart.


Dart . . , .

, ( ), , .


void myBigLoop(){
    for (int i = 0; i < 1000000; i++){
        _doSomethingSynchronously();
    }
}

, myBigLoop() . , - , , .


Dart


Dart, , Event Loop.


Flutter- ( Dart-), — Thread, — (Isolate). , .


, :


  1. (Queues) MicroTask ()
    Event (), FIFO (.: first in first out, .. ,
    , ),
  2. main() ,
  3. Event Loop ( )

,
Event Loop
, : MicroTask Event.


Event Loop "" ,
"". ,
Dart-, "" :


void eventLoop(){
    while (microTaskQueue.isNotEmpty){
        fetchFirstMicroTaskFromQueue();
        executeThisMicroTask();
        return;
    }

    if (eventQueue.isNotEmpty){
        fetchFirstEventFromQueue();
        executeThisEventRelatedCode();
    }
}

, MicroTask Event. ?


MicroTask


, , - , Event Loop.


. - , - :


MyResource myResource;

    ...

    void closeAndRelease() {
        scheduleMicroTask(_dispose);
        _close();
    }

    void _close(){
        // ,     
        //   
        ...
    }

    void _dispose(){
        // ,    
        //   ,  _close()
        // 
    }

-, , . , scheduleMicroTask() 7 . Event.


Event


, :


  • ,
    • /
    • ...
  • Future

, , Event.


, MicroTask , Event Loop Event .


, Futures Event.


Futures


Future , ( ) - .


, Future:


  • , Dart
  • , Future,
    Event
  • Future (incomplete)
  • , ( Future)

, Future Event,
Event Loop .


( ) then()
catchError() Future.


, :


void main(){
    print('Before the Future');
    Future((){
        print('Running the Future');
    }).then((_){
        print('Future is complete');
    });
    print('After the Future');
}

, :


Before the Future
After the Future
Running the Future
Future is complete

:


  1. print('Before the Future')
  2. (){print('Running the Future');} Event
  3. print('After the Future')
  4. Event Loop 2
  5. , then()

:


Future , , Event Loop

(async)


async, Dart , :


  • Future
  • , await,
  • Future, await

, await , [ Future], .
Event Loop...


,
,


void main() async {
  methodA();
  await methodB();
  await methodC('main');
  methodD();
}

methodA(){
  print('A');
}

methodB() async {
  print('B start');
  await methodC('B');
  print('B end');
}

methodC(String from) async {
  print('C start from $from');

  Future((){                // <==     -  
    print('C running Future from $from');
  }).then((_){
    print('C end of Future from $from');
  });

  print('C end from $from');  
}

methodD(){
  print('D');
}

:


A
B start
C start from B
C end from B
B end
C start from main
C end from main
D
C running Future from B
C end of Future from B
C running Future from main
C end of Future from main

, methodC() . , , .


, methodD() , :


void main() async {
  methodA();
  await methodB();
  await methodC('main');
  methodD();  
}

methodA(){
  print('A');
}

methodB() async {
  print('B start');
  await methodC('B');
  print('B end');
}

methodC(String from) async {
  print('C start from $from');

  await Future((){                  // <==  
    print('C running Future from $from');
  }).then((_){
    print('C end of Future from $from');
  });
  print('C end from $from');  
}

methodD(){
  print('D');
}

:


A
B start
C start from B
C running Future from B
C end of Future from B
C end from B
B end
C start from main
C running Future from main
C end of Future from main
C end from main
D

, await Future methodC() .


:


, , Event Loop

. . method1method2? ?


void method1(){
  List<String> myArray = <String>['a','b','c'];
  print('before loop');
  myArray.forEach((String value) async {
    await delayedPrint(value);
  });  
  print('end of loop');
}

void method2() async {
  List<String> myArray = <String>['a','b','c'];
  print('before loop');
  for(int i=0; i<myArray.length; i++) {
    await delayedPrint(myArray[i]);
  }
  print('end of loop');
}

Future<void> delayedPrint(String value) async {
  await Future.delayed(Duration(seconds: 1));
  print('delayedPrint: $value');
}

: .


, method1 forEach() . , async ( Future). await, Event. , : print('end of loop'). Event Loop 3 .


method2, ( ) — .


, ,
Event Loop...



, Flutter? ?


, Isolate ().



, Isolate Dart Thread ().


Thread.


Flutter . .

Event Loop.


(MicroTask Event).


.


Dart.



, .


1.


() API, Dart.


1.1. 1:


, , , "" "" .


, , . SendPort ( , , /, ).


, "" " " , "". :


//
//   
//     
//    
//
SendPort newIsolateSendPort;

//
//   
//
Isolate newIsolate;

//
// ,    
//   
//
void callerCreateIsolate() async {
    //
    //   ReceivePort  
    // SendPort  
    //
    ReceivePort receivePort = ReceivePort();

    //
    //   
    //
    newIsolate = await Isolate.spawn(
        callbackFunction,
        receivePort.sendPort,
    );

    //
    //     ""
    //
    newIsolateSendPort = await receivePort.first;
}

//
//    
//
static void callbackFunction(SendPort callerSendPort){
    //
    //   SendPort   
    //  ""
    //
    ReceivePort newIsolateReceivePort = ReceivePort();

    //
    //  ""   SendPort  
    //
    callerSendPort.send(newIsolateReceivePort.sendPort);

    //
    //  
    //
}

:

1.2. 2:


, , :


//
// ,     
//   
// 
//     ""
//   String (   )
//
Future<String> sendReceive(String messageToBeSent) async {
    //
    //     
    //
    ReceivePort port = ReceivePort();

    //
    //   ,  
    //  ,   
    //   
    //
    newIsolateSendPort.send(
        CrossIsolatesMessage<String>(
            sender: port.sendPort,
            message: messageToBeSent,
        )
    );

    //
    //     
    //
    return port.first;
}

//
// Callback-    
//
static void callbackFunction(SendPort callerSendPort){
    //
    //   SendPort   
    //  
    //
    ReceivePort newIsolateReceivePort = ReceivePort();

    //
    //  ""   SendPort  
    //
    callerSendPort.send(newIsolateReceivePort.sendPort);

    //
    //  ,    ,
    //    
    //
    newIsolateReceivePort.listen((dynamic message){
        CrossIsolatesMessage incomingMessage = message as CrossIsolatesMessage;

        //
        //  
        //
        String newMessage = "complemented string " + incomingMessage.message;

        //
        //   
        //
        incomingMessage.sender.send(newMessage);
    });
}

//
//  
//
class CrossIsolatesMessage<T> {
    final SendPort sender;
    final T message;

    CrossIsolatesMessage({
        @required this.sender,
        this.message,
    });
}

1.3. 3:


, :


void dispose(){
    newIsolate?.kill(priority: Isolate.immediate);
    newIsolate = null;
}

1.4. — Stream


, "" "" (Streams). Single-Listener Stream ( ).


2. (One-shot computation)


, , Dart compute,


  • ,
  • — -
  • .

: ( ).

3.


, ,


(Platform-Channel communication) (main isolate). , .

, ,
.


Future


, :


  • (user friendliness)

, (user experiences lags), .


, :


  1. ,
    ( )
  2. ,
    , — Event Loop Futures
  3. ,
    , —

, , , Futures ( async-) — Futures Event Loop "" . , ( - , ).


, Future — , .


  • => Future
  • =>

:


  • JSON, (HttpRequest),
    => compute
  • : =>
  • ( ..) =>
  • : , , .


, , Event Loop .


Penting juga untuk tidak lupa bahwa Flutter( Dart) adalah single-threaded, oleh karena itu, untuk memuaskan pengguna, pengembang harus yakin bahwa aplikasi akan bekerja semulus mungkin. Futuresdan - alat yang ampuh untuk membantu mencapai tujuan ini.


Semoga berhasil


All Articles