Heim >Backend-Entwicklung >C++ >Warum führt das asynchrone Sperren auf Schlüsselbasis zu zeitweiligen Dateizugriffsfehlern und wie kann ein Ansatz zur Referenzzählung dies verbessern?

Warum führt das asynchrone Sperren auf Schlüsselbasis zu zeitweiligen Dateizugriffsfehlern und wie kann ein Ansatz zur Referenzzählung dies verbessern?

Susan Sarandon
Susan SarandonOriginal
2025-01-15 09:35:43245Durchsuche

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

Asynchrone schlüsselbasierte Sperrung: Eine Quelle zeitweiliger Dateizugriffsfehler

Der Cache-Mechanismus der ImageProcessor-Bibliothek, der eine asynchrone Sperre auf Basis eines Schlüssels verwendet, leidet unter zeitweiligen Dateizugriffsfehlern. Dies ist auf einen Designfehler innerhalb der AsyncDuplicateLock-Klasse zurückzuführen.

Der Fehler: Vorzeitige Semaphorfreigabe

Der ursprüngliche AsyncDuplicateLock-Code entfernt SemaphoreSlim-Instanzen vorzeitig aus dem ConcurrentDictionary, bevor das Semaphor freigegeben wird. Dies führt zu einer übermäßigen Abwanderung von Semaphoren und potenziellen Fehlern, da nach dem Entfernen möglicherweise auf Semaphoren zugegriffen werden kann.

Lösung: Ein robuster Ansatz zur Referenzzählung

Eine überlegene Lösung nutzt die Referenzzählung. Jedes Semaphor im Wörterbuch verwaltet einen Referenzzähler. Eine einzelne Sperre garantiert die Atomizität zum Dekrementieren der Anzahl und zum Entfernen des Semaphors, sodass kein ConcurrentDictionary.

erforderlich ist
<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>

Dieser überarbeitete Ansatz garantiert, dass Semaphoren nur dann freigegeben werden, wenn sie nicht mehr benötigt werden, wodurch zeitweilige Dateizugriffsfehler während Cache-Vorgängen wirksam verhindert werden.

Das obige ist der detaillierte Inhalt vonWarum führt das asynchrone Sperren auf Schlüsselbasis zu zeitweiligen Dateizugriffsfehlern und wie kann ein Ansatz zur Referenzzählung dies verbessern?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn