Flutter同步控制插件synchronized的使用

发布于 1周前 作者 yibo5220 来自 Flutter

Flutter同步控制插件synchronized的使用

描述

synchronized 是一个基本的锁机制,用于防止异步代码的并发访问。它旨在提供类似于临界区(Critical Sections)的功能,并提供简单易用的 API,其风格类似于 Java 的 synchronized 关键字。

目标

该库的目标是为单线程(单隔离区)环境下的 Dart 提供一种解决方案,确保某些异步操作可以无冲突地运行。它可以用于:

  • 为没有事务机制的数据库系统(如 MongoDB、文件系统)提供事务支持。
  • 在 HTML 应用中确保某些异步 UI 操作不会发生冲突(如登录、过渡动画等)。

功能特性

  • 默认情况下,锁不是可重入的。
  • 支持超时。
  • 支持可重入锁(使用 Zone 实现)。
  • 行为一致性(例如,如果锁已解锁,则调用 synchronized 可以获取锁)。
  • 正确报告值和错误给调用者。
  • 支持浏览器、DartVM 和 Flutter 环境。
  • 除了 SDK 本身外,没有其他依赖。

使用方法

基本用法示例

import 'package:synchronized/synchronized.dart';

main() async {
  // 创建一个锁对象,用于防止并发访问数据
  var lock = Lock();
  
  await lock.synchronized(() async {
    // 只有这一个块可以运行(一次),直到完成
  });
}

可重入锁

如果你需要一个可重入锁,你可以这样做:

var lock = Lock(reentrant: true);

await lock.synchronized(() async {
  // 执行一些操作
  
  await lock.synchronized(() async {
    // 其他操作
  });
});

返回值

返回值也会被正确传递:

int value = await lock.synchronized(() {
  return 1;
});

使用扩展方法

通过导入 package:synchronized/extension.dart,你可以将任何对象转换为锁,并在其上调用 synchronized() 方法:

import 'package:synchronized/extension.dart';

class MyClass {
  Future performAction() {
    // 实例级别锁定
    return synchronized(() async {
      // ... 不会被中断的操作
    });
  }
}

示例代码

以下是一个完整的示例,展示了如何使用 synchronized 插件来同步两个异步任务:

import 'dart:async';
import 'dart:io';
import 'package:synchronized/synchronized.dart';

Future<void> writeSlow(int value) async {
  await Future<void>.delayed(const Duration(milliseconds: 1));
  stdout.write(value);
}

Future<void> write(List<int> values) async {
  for (var value in values) {
    await writeSlow(value);
  }
}

Future<void> write1234() async {
  await write([1, 2, 3, 4]);
}

class Demo {
  Future<void> test1() async {
    stdout.writeln('not synchronized');
    // ignore: unawaited_futures
    write1234();
    // ignore: unawaited_futures
    write1234();

    await Future<void>.delayed(const Duration(milliseconds: 50));
    stdout.writeln();
  }

  Future<void> test2() async {
    stdout.writeln('synchronized');

    var lock = Lock();
    // ignore: unawaited_futures
    lock.synchronized(write1234);
    // ignore: unawaited_futures
    lock.synchronized(write1234);

    await Future<void>.delayed(const Duration(milliseconds: 50));

    stdout.writeln();
  }

  Future<void> readme1() async {
    var lock = Lock();

    await lock.synchronized(() async {
      // do some stuff
    });
  }

  Future<void> readme2() async {
    var lock = Lock();
    if (!lock.locked) {
      await lock.synchronized(() async {
        // do some stuff
      });
    }
  }

  Future<void> readme3() async {
    var lock = Lock();
    var value = await lock.synchronized(() {
      return 1;
    });
    stdout.writeln('got value: $value');
  }
}

Future<void> main() async {
  var demo = Demo();

  await demo.test1(); // 输出:11223344
  await demo.test2(); // 输出:12341234
  await demo.readme1();
  await demo.readme1();
  await demo.readme3();
}

注意事项

  • Lock 实例必须在所有调用之间共享,以便有效地防止并发执行。通常,你会创建一个全局或静态的 Lock 实例来防止对全局资源的并发访问,或者创建一个类实例级别的 Lock 来防止对类实例数据和资源的并发修改。
  • 对于多锁情况,MultiLock 可以用于同时同步多个锁。

希望这些信息能帮助你在 Flutter 项目中更好地理解和使用 synchronized 插件!如果有任何问题或需要进一步的帮助,请随时提问。


更多关于Flutter同步控制插件synchronized的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter同步控制插件synchronized的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,synchronized 并不是官方提供的一个直接用于同步控制的插件或关键字。Flutter和Dart语言本身更偏向于使用内置的并发控制机制,如 Isolates(独立执行的Dart代码块),Futures(异步操作的结果),以及 Streams(事件流)来处理并发任务。

不过,如果你希望在Flutter应用中实现类似Java中synchronized的功能,即确保某些代码块在同一时间内只能被一个线程(或Dart中的Isolate)访问,你可以使用Dart的Mutex(互斥锁)来实现。

下面是一个简单的例子,展示了如何使用Mutex来同步控制对共享资源的访问:

import 'dart:async';
import 'dart:collection';

void main() async {
  // 创建一个Mutex对象
  final Mutex mutex = Mutex();
  
  // 共享资源
  int sharedCounter = 0;

  // 异步函数,模拟对共享资源的访问
  void incrementCounter() async {
    // 锁定Mutex
    await mutex.withLock(async () async {
      // 在锁内安全地修改共享资源
      sharedCounter++;
      print('Counter after increment: $sharedCounter');
      
      // 模拟一些异步操作
      await Future.delayed(Duration(seconds: 1));
    });
    // 锁在离开withLock作用域时自动释放
  }

  // 启动多个任务同时访问共享资源
  List<Future> futures = [];
  for (int i = 0; i < 10; i++) {
    futures.add(incrementCounter());
  }

  // 等待所有任务完成
  await Future.wait(futures);

  print('Final counter value: $sharedCounter');
}

在这个例子中,我们使用了dart:async包中的Mutex类来创建一个互斥锁。Mutex.withLock方法接受一个函数作为参数,并在执行该函数时持有锁,确保在同一时间内只有一个Isolate可以执行这个函数。当函数执行完毕后,锁会自动释放。

请注意,Dart的Mutex和Java的synchronized在底层实现和用途上有所不同,但它们在提供同步控制方面的目标是相似的。在Flutter中,由于UI更新是单线程的(通过Dart的EventLoop管理),你通常不需要在UI线程上使用复杂的同步机制。然而,在处理后台任务或与其他Isolate通信时,同步控制就变得非常重要了。

回到顶部