搜索插件、代码仓与 APP 分类

插件详情v3.1.0

mutex

互斥锁,包含普通锁和读写锁的实现

AndroidiOSWebmacOSWindowsLinux
近 30 天下载
34.8万
喜欢数
117
Pub 分数
150

安装插件

flutter pub add mutex

插件介绍

基于插件公开信息、社区数据与项目使用情况整理的选型参考。

该 mutex 包为 Dart 提供了互斥机制,包括标准和读写锁实现。它可确保在多个 isolate 中对共享资源进行安全的并发访问,防止竞争条件。该包专为多线程环境设计,提供独占和共享锁定功能。非常适合用于异步应用程序中的状态管理,支持所有主要平台,包括移动、Web 和桌面。其实现轻量且与 Flutter 及 Dart 的并发模型无缝集成。

适合场景

  • 在隔离区中同步对共享数据的访问
  • 保护多隔离区应用程序中的关键部分
  • 启用读写并发以实现高性能数据访问
  • 使用隔离通信管理Flutter应用中的状态
  • 实现线程安全的缓存或队列
  • 在后台任务中协调资源访问

主要特点

  • 用于独占访问的标准互斥锁
  • 用于并发读取的读写互斥锁
  • 跨平台支持(Android、iOS、Web、macOS、Windows、Linux)
  • 轻量且高效的实现
  • 用于锁获取和释放的简单 API
  • 跨隔离区的线程安全操作

适合对象

  • 开发并发 Dart/Flutter 应用的开发者
  • 需要隔离级别同步的应用程序
  • 高性能数据结构需要读写锁
  • 必须避免竞争条件的系统
  • 使用隔离区进行并行处理的团队

使用建议

  • 需要仔细处理以避免死锁
  • 不适用于单个隔离场景
  • 频繁锁争用带来的性能影响
  • 必须在隔离边界内使用
  • 受限于 Dart 的隔离区模型,而非操作系统级线程
  • 锁应尽快释放,以防止阻塞

原始 README

以下为关联源码仓库的 README 原文快照,最新内容请访问源码仓库。

mutex

A library for creating locks to ensure mutual exclusion when running critical sections of code.

Purpose

Mutexes can be used to protect critical sections of code to prevent race conditions.

Although Dart uses a single thread of execution, race conditions can still occur when asynchronous operations are used inside critical sections. For example,

x = 42;
synchronousOperations(); // this does not modify x
assert(x == 42); // x will NOT have changed

y = 42; // a variable that other asynchronous code can modify
await asynchronousOperations(); // this does NOT modify y, but...
// There is NO GUARANTEE other async code didn't run and change it!
assert(y == 42 || y != 42); // WARNING: y might have changed

An example is when Dart is used to implement a server-side Web server that updates a database (assuming database transactions are not being used). The update involves querying the database, performing calculations on those retrieved values, and then updating the database with the result. You don't want the database to be changed by "something else" while performing the calculations, since the results you would write will not incorporate those other changes. That "something else" could be the same Web server handling another request in parallel.

This package provides a normal mutex and a read-write mutex.

Mutex

A mutex guarantees at most only one lock can exist at any one time.

If the lock has already been acquired, attempts to acquire another lock will be blocked until the lock has been released.

import 'package:mutex/mutex.dart';

...

final m = Mutex();

Acquiring the lock before running the critical section of code, and then releasing the lock.

await m.acquire();
// No other lock can be acquired until the lock is released

try {
  // critical section with asynchronous code
  await ...
} finally {
  m.release();
}
protect

The following code uses the protect convenience method to do the same thing as the above code. Use the convenence method whenever possible, since it ensures the lock will always be released.

await m.protect(() async {
  // critical section
});

If the critial section returns a Future to a value, the protect convenience method will return a Future to that value.

final result = await m.protect<int>(() async {
  // critical section
  return valueFromCriticalSection;
});
// result contains the valueFromCriticalSection

Read-write mutex

A read-write mutex allows multiple reads locks to be exist simultaneously, but at most only one write lock can exist at any one time. A write lock and any read locks cannot both exist together at the same time.

If there is one or more read locks, attempts to acquire a write lock will be blocked until all the read locks have been released. But attempts to acquire more read locks will not be blocked. If there is a write lock, attempts to acquire any lock (read or write) will be blocked until that write lock is released.

A read-write mutex can also be described as a single-writer mutex, multiple-reader mutex, or a reentrant lock.

import 'package:mutex/mutex.dart';

...

final m = ReadWriteMutex();

Acquiring a write lock:

await m.acquireWrite();
// No other locks (read or write) can be acquired until released

try {
  // critical write section with asynchronous code
  await ...
} finally {
  m.release();
}

Acquiring a read lock:

await m.acquireRead();
// No write lock can be acquired until all read locks are released,
// but additional read locks can be acquired.

try {
  // critical read section with asynchronous code
  await ...
} finally {
  m.release();
}
protectWrite and protectRead

The following code uses the protectWrite and protectRead convenience methods to do the same thing as the above code. Use the convenence method whenever possible, since it ensures the lock will always be released.

await m.protectWrite(() async {
  // critical write section
});

await m.protectRead(() async {
  // critical read section
});

If the critial section returns a Future to a value, these convenience methods will return a Future to that value.

final result1 await m.protectWrite<String>(() async {
  // critical write section
  return valueFromCritialSection1;
});
// result1 contains the valueFromCriticalSection1

final result2 = await m.protectRead(() async {
  // critical read section
  return valueFromCritialSection2;
});
// result2 contains the valueFromCriticalSection2

When mutual exclusion is not needed

The critical section should always contain some asynchronous code. If the critical section only contains synchronous code, there is no need to put it in a critical section. In Dart, synchronous code cannot be interrupted, so there is no need to protect it using mutual exclusion.

Also, if the critical section does not involve data or shared resources that can be accessed by other asynchronous code, it also does not need to be protected. For example, if it only uses local variables that other asynchronous code won't have access to: while the other asynchronous code could run, it won't be able to make unexpected changes to the local variables it can't access.

Features and bugs

Please file feature requests and bugs at the issue tracker.

所属分类

源码仓库

使用此插件的项目