ホームページ > バックエンド開発 > C++ > 断続的なファイル アクセス エラーを防ぐために SemaphoreSlim を使用して非同期ロックを正しく実装する方法

断続的なファイル アクセス エラーを防ぐために SemaphoreSlim を使用して非同期ロックを正しく実装する方法

Barbara Streisand
リリース: 2025-01-15 09:49:50
オリジナル
889 人が閲覧しました

How to Correctly Implement Asynchronous Locking Using SemaphoreSlim to Prevent Intermittent File Access Errors?

非同期ロックによる断続的なファイル アクセス エラーへの対処

最近、ImageProcessor ライブラリで、非同期ロックの欠陥が原因で、キャッシュの更新中に断続的なファイル アクセス エラーが発生しました。この記事では、元の欠陥のある実装を分析し、堅牢な解決策を提供します。

元のアプローチでは、ハッシュ化された URL を非同期ロックのキーとして使用し、SemaphoreSlim インスタンスを ConcurrentDictionary に格納して、単一キーのロックを確保していました。 重大な欠陥は、セマフォを解放するSemaphoreSlim前にを辞書から同期的に削除することにありました。この競合状態により、ファイル アクセスの競合が発生しました。

次のコード スニペットは、問題のあるキー/

の参照を示しています。SemaphoreSlim

<code class="language-csharp">private static readonly Dictionary<object, RefCounted<SemaphoreSlim>> SemaphoreSlims
                        = new Dictionary<object, RefCounted<SemaphoreSlim>>();

private SemaphoreSlim GetOrCreate(object key)
{
    RefCounted<SemaphoreSlim> item;
    lock (SemaphoreSlims)
    {
        if (SemaphoreSlims.TryGetValue(key, out item))
        {
            ++item.RefCount;
        }
        else
        {
            item = new RefCounted<SemaphoreSlim>(new SemaphoreSlim(1, 1));
            SemaphoreSlims[key] = item;
        }
    }
    return item.Value;
}</code>
ログイン後にコピー
以下は、同時実行の問題を解決した修正された

クラスです。AsyncDuplicateLock

<code class="language-csharp">public sealed class AsyncDuplicateLock
{
    private sealed class RefCounted<T>
    {
        public RefCounted(T value)
        {
            RefCount = 1;
            Value = value;
        }

        public int RefCount { get; set; }
        public T Value { get; private set; }
    }

    private static readonly Dictionary<object, RefCounted<SemaphoreSlim>> SemaphoreSlims
                        = new Dictionary<object, RefCounted<SemaphoreSlim>>();

    private SemaphoreSlim GetOrCreate(object key)
    {
        RefCounted<SemaphoreSlim> item;
        lock (SemaphoreSlims)
        {
            if (SemaphoreSlims.TryGetValue(key, out item))
            {
                ++item.RefCount;
            }
            else
            {
                item = new RefCounted<SemaphoreSlim>(new SemaphoreSlim(1, 1));
                SemaphoreSlims[key] = item;
            }
        }
        return item.Value;
    }

    public IDisposable Lock(object key)
    {
        GetOrCreate(key).Wait();
        return new Releaser { Key = key };
    }

    public async Task<IDisposable> LockAsync(object key)
    {
        await GetOrCreate(key).WaitAsync().ConfigureAwait(false);
        return new Releaser { Key = key };
    }

    private sealed class Releaser : IDisposable
    {
        public object Key { get; set; }

        public void Dispose()
        {
            RefCounted<SemaphoreSlim> item;
            lock (SemaphoreSlims)
            {
                item = SemaphoreSlims[Key];
                --item.RefCount;
                if (item.RefCount == 0)
                    SemaphoreSlims.Remove(Key);
            }
            item.Value.Release();
        }
    }
}</code>
ログイン後にコピー
この改訂された実装により、ディクショナリから削除される

前にセマフォが解放されるようになり、競合状態が解消され、断続的なファイル アクセス エラーが解決されます。

以上が断続的なファイル アクセス エラーを防ぐために SemaphoreSlim を使用して非同期ロックを正しく実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート