パッケージ、リポジトリ、アプリカテゴリを検索

パッケージ詳細v3.1.0

mutex

排他制御と通常および読み書きミューテックスの実装

AndroidiOSWebmacOSWindowsLinux
30日間ダウンロード
34.8万
いいね数
117
Pub ポイント
150

パッケージをインストール

flutter pub add mutex

パッケージ概要

公開情報に基づく選定ガイドです。参考としてご利用ください。

mutex パッケージは、Dart に排他制御メカニズムを提供しており、標準および読み書きロックの実装を含んでいます。複数の isolate 間で共有リソースへの安全な同時アクセスを可能にし、競合状態を防ぎます。マルチスレッド環境向けに設計されており、排他的および共有ロック機能を提供します。非同期アプリケーションにおける状態管理に最適で、モバイル、Web、デスクトップを含むすべての主要プラットフォームをサポートしています。実装は軽量であり、Flutter および Dart の並行処理モデルとシームレスに統合されています。

用途

  • 隔離領域における共有データへのアクセスの同期
  • マルチ隔離アプリにおける重要なセクションの保護
  • 高パフォーマンスなデータアクセスのための読み書き並行処理を有効にする
  • Isolate通信を用いたFlutterアプリケーションにおける状態管理
  • スレッドセーフなキャッシュまたはキューの実装
  • バックグラウンドタスクでのリソースアクセスの調整

主な機能

  • 排他的アクセス用の標準的なミューテックス
  • 並行読み取り用の読み書きミューテックス
  • クロスプラットフォーム対応(Android、iOS、Web、macOS、Windows、Linux)
  • 軽量で効率的な実装
  • ロックの取得と解放のためのシンプルな API
  • 隔離領域間のスレッドセーフな操作

適している対象

  • 並行なDart/Flutterアプリを開発する開発者
  • 隔離レベルの同期を必要とするアプリケーション
  • 読み書きロックが必要な高性能データ構造
  • 競合状態を回避しなければならないシステム
  • 並列処理に孤立体を使用するチーム

注意事項

  • デッドロックを回避するため、注意深く取り扱う必要があります
  • 単一の分離シナリオには適していません
  • 頻繁なロック競合によるパフォーマンスへの影響
  • 隔離境界内で使用する必要がある
  • Dartのイソレートモデルに制限され、OSレベルのスレッドではない
  • ブロッキングを防ぐために、ロックはすみやかに解放するべきです

元の 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.

カテゴリー

ソースリポジトリ

このパッケージを使用しているプロジェクト