synchronized: A Simple Lock for Asynchronous Dart Code
Published on by Flutter News Hub
In asynchronous Dart programming, it's crucial to prevent concurrent access to shared resources, which can lead to unexpected behavior and deadlocks. The synchronized
package provides a straightforward lock mechanism to address this issue.
How It Works
The synchronized
package implements basic lock functionality, ensuring that only one asynchronous task can access a shared resource at a time. It works by creating a queue and executing tasks one at a time.
Usage
To use the synchronized
package, you can create a Lock
object:
import 'package:synchronized/synchronized.dart';
final lock = Lock();
Then, you can use the synchronized()
method to wrap your asynchronous task:
await lock.synchronized(() async {
// Code that should be executed without concurrent access
});
Features
The synchronized
package offers several useful features:
- Non-reentrant locks: By default, locks are not reentrant, meaning a task cannot reacquire the same lock while it's already holding it.
-
Reentrant locks: Using
Zone
s, you can create reentrant locks that allow tasks to reacquire the same lock multiple times. - Timeout support: You can specify a timeout for lock acquisition, after which an exception will be thrown.
-
Consistent behavior: The
synchronized()
method ensures that if a lock is unlocked, the next call tosynchronized()
will acquire the lock immediately. -
Compatible with multiple platforms:
synchronized
works on web, mobile, and server environments.
Example
Consider the following code:
Future writeSlow(int value) async {
await Future.delayed(Duration(milliseconds: 1));
stdout.write(value);
}
Future write(List values) async {
for (int value in values) {
await writeSlow(value);
}
}
Future write1234() async {
await write([1, 2, 3, 4]);
}
void main() async {
await lock.synchronized(write1234);
await lock.synchronized(write1234);
}
Without the synchronized
package, running write1234()
twice would print the numbers out of order. However, using the synchronized
lock, the output will be in the correct order (1234 1234).
Extension Method
You can also use the synchronized
extension method:
class MyClass {
Future myMethod() async =>
await synchronized(() async { step1(); step2(); step3(); });
}
This allows you to lock on any object and perform synchronized operations.
Conclusion
The synchronized
package provides a simple and effective way to prevent concurrent access to shared resources in Dart, ensuring the reliable execution of asynchronous tasks.