Introduction
I have introduced a lot of asynchronous programming techniques in dart before. I don’t know if you have found a problem. If it is in the asynchronous programming of java, it will definitely mention the lock and concurrency mechanism, but for dart, it seems that I have never heard much Thread and concurrency issues, why is this?
Today, I will explain to you the isolation mechanism in dart, and everyone will understand.
Isolation mechanism in dart
Dart is a single-threaded language, but as a single-threaded language, dart supports asynchronous features such as Future and Stream. All of this is the result of the isolation mechanism and the event loop.
First look at the isolation mechanism in dart.
The so-called isolation refers to a specific space where dart runs. This space has a separate memory and a single-threaded event loop.
As shown below:
In other languages such as java or c++, multiple threads share memory space. Although it brings a convenient way for concurrency and data communication, it also causes difficulties in concurrent programming.
Because we need to consider the synchronization of data between multiple threads, there are a lot of additional locking mechanisms, and those who know it in detail or have used it should be very annoying.
The biggest drawback of multithreading is that programmers' Luo Ji thinking and programming skills are required to be good enough to be able to design a perfectly running multithreaded program.
But in dart, these are not problems. All threads in dart have their own running space, and the job of this thread is to run the event loop.
Then the problem is coming, the main thread is processing the event loop, but if it encounters a very time-consuming operation, what should I do? If it runs directly in the main thread, it may cause the main thread to block.
Dart also fully considers this problem, so dart provides an Isolate class to manage isolation.
Because the dart program itself runs in an isolate, if an isolate is defined in dart, then this isolate usually represents another isolate that needs to communicate with the current isolate.
Generate an Isolate
So how to generate an Isolate in the current dart program?
Isolate provides three generation methods.
A very commonly used method is Isolate's factory method spawn:
external static Future<Isolate> spawn<T>(
void entryPoint(T message), T message,
{bool paused = false,
bool errorsAreFatal = true,
SendPort? onExit,
SendPort? onError,
@Since("2.3") String? debugName});
spawn will create a new Isolate, calling it requires several parameters:
EntryPoint represents the function that needs to be called when generating a new Isolate. entryPoint accepts a message parameter. Generally speaking, message is a SendPort object used for communication between two Isolates.
paused indicates whether the newly generated Isolate is in a paused state, which is equivalent to:
isolate.pause(isolate.pauseCapability)
If you need to cancel the pause state later, you can call:
isolate.resume(isolate.pauseCapability)
errorsAreFatal corresponds to the setErrorsFatal method.
onExit corresponds to addOnExitListener, onError corresponds to addErrorListener.
debugName represents the name displayed by Isolate during debugging.
If spawn fails, IsolateSpawnException will be thrown:
class IsolateSpawnException implements Exception {
/// Error message reported by the spawn operation.
final String message;
@pragma("vm:entry-point")
IsolateSpawnException(this.message);
String toString() => "IsolateSpawnException: $message";
}
The spawn method generates the same Isolate as the current code. If you want to use different codes to generate, you can use spawnUri to generate different codes by passing in the corresponding Uri address.
external static Future<Isolate> spawnUri(
Uri uri,
List<String> args,
var message,
{bool paused = false,
SendPort? onExit,
SendPort? onError,
bool errorsAreFatal = true,
bool? checked,
Map<String, String>? environment,
@Deprecated('The packages/ dir is not supported in Dart 2')
Uri? packageRoot,
Uri? packageConfig,
bool automaticPackageResolution = false,
@Since("2.3")
String? debugName});
Another way is to use the constructor of Isolate:
Isolate(this.controlPort, {this.pauseCapability, this.terminateCapability});
It has three parameters. The first parameter is controlPort, which represents the control right of another isolate, and the latter two capabilities are a subset of the original isolate, indicating whether there is a pause or terminate permission.
The general usage is as follows:
Isolate isolate = findSomeIsolate();
Isolate restrictedIsolate = Isolate(isolate.controlPort);
untrustedCode(restrictedIsolate);
Interaction between isolates
All dart code runs in Isolate, and then the code can only access the class and value in the same isolate. Then the communication between multiple isolates can be realized by ReceivePort and SendPort.
First look at SendPort, SendPort is a kind of Capability:
abstract class SendPort implements Capability
SendPort is used to send messages to ReceivePort. Messages can have many types, including:
Null, bool, int, double, String, List, Map, TransferableTypedData, SendPort and Capability.
Note that the send action is completed immediately.
In fact, SendPort was created by ReceivePort. One ReceivePort can receive multiple SendPorts.
ReceivePort is a kind of Stream:
abstract class ReceivePort implements Stream<dynamic>
As a Stream, it provides a listen to process the received message:
StreamSubscription<dynamic> listen(void onData(var message)?,
{Function? onError, void onDone()?, bool? cancelOnError});
one example
After talking about so many principles, some students may ask, so how do you use it?
Here comes the example:
import 'dart:isolate';
var isolate;
void entryPoint(SendPort sendPort) {
int counter = 0;
sendPort.send("counter:$counter");
}
void main() async{
final receiver = ReceivePort();
receiver.listen((message) {
print( "接收到消息 $message");
});
isolate = await Isolate.spawn(entryPoint, receiver.sendPort);
}
In the main thread, we create a ReceivePort, and then call its listen method to listen to the messages sent by sendPort.
Then spawn a new Isolate, this Isolate will call the entryPoint method after initialization.
In this entryPoint method, sendPort is used to send messages to ReceivePort.
Finally run, print:
接收到消息 counter:0
Summarize
The above is the isolation mechanism and the use of Isolate in dart.
This article has been included in http://www.flydean.com/25-dart-isolates/
The most popular interpretation, the most profound dry goods, the most concise tutorial, and many tips you don't know are waiting for you to discover!
Welcome to pay attention to my official account: "programs, those things", know the technology, know you better!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。