ホームページ >バックエンド開発 >C++ >キーに基づく非同期ロックが断続的なファイル アクセス エラーを引き起こすのはなぜですか?また、参照カウントのアプローチでどのように改善できるのでしょうか?

キーに基づく非同期ロックが断続的なファイル アクセス エラーを引き起こすのはなぜですか?また、参照カウントのアプローチでどのように改善できるのでしょうか?

Susan Sarandon
Susan Sarandonオリジナル
2025-01-15 09:35:43239ブラウズ

Why does asynchronous locking based on a key cause intermittent file access errors, and how can a reference-counting approach improve it?

非同期キーベースのロック: 断続的なファイル アクセス エラーの原因

ImageProcessor ライブラリのキャッシュ メカニズムはキーに基づく非同期ロックを採用しているため、断続的なファイル アクセス エラーが発生します。 これは、AsyncDuplicateLock クラス内の設計上の欠陥が原因です。

欠陥: セマフォの早期リリース

元の AsyncDuplicateLock コードは、セマフォを解放する前に SemaphoreSlim から ConcurrentDictionary インスタンスを途中で削除します。これにより、セマフォが削除後にアクセスされる可能性があるため、過剰なセマフォ チャーンと潜在的なエラーが発生します。

解決策: 堅牢な参照カウント手法

優れたソリューションは参照カウントを利用します。 ディクショナリ内の各セマフォは参照カウントを維持します。 単一のロックにより、カウントのデクリメントとセマフォの削除の原子性が保証され、ConcurrentDictionary.

が不要になります。
<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>

この改訂されたアプローチにより、セマフォが不要になった場合にのみ解放されることが保証され、キャッシュ操作中の断続的なファイル アクセス エラーが効果的に防止されます。

以上がキーに基づく非同期ロックが断続的なファイル アクセス エラーを引き起こすのはなぜですか?また、参照カウントのアプローチでどのように改善できるのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。