Maison > développement back-end > C++ > Comment implémenter correctement le verrouillage asynchrone à l'aide de SemaphoreSlim pour éviter les erreurs d'accès intermittent aux fichiers ?

Comment implémenter correctement le verrouillage asynchrone à l'aide de SemaphoreSlim pour éviter les erreurs d'accès intermittent aux fichiers ?

Barbara Streisand
Libérer: 2025-01-15 09:49:50
original
889 Les gens l'ont consulté

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

Résolution des erreurs d'accès intermittent aux fichiers avec le verrouillage asynchrone

La bibliothèque ImageProcessor a récemment rencontré des erreurs intermittentes d'accès aux fichiers lors des mises à jour du cache, dues à un verrouillage asynchrone défectueux. Cet article analyse l'implémentation défectueuse d'origine et fournit une solution robuste.

L'approche originale utilisait des URL hachées comme clés pour les verrous asynchrones, stockant les instances SemaphoreSlim dans un ConcurrentDictionary pour garantir un verrouillage à clé unique. Le défaut critique résidait dans la suppression synchrone du SemaphoreSlim du dictionnaire avant de libérer le sémaphore. Cette condition de concurrence a conduit à des conflits d'accès aux fichiers.

L'extrait de code suivant illustre le référencement de clé/SemaphoreSlim problématique :

<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>
Copier après la connexion

Ci-dessous se trouve la classe AsyncDuplicateLock corrigée, résolvant le problème de concurrence :

<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>
Copier après la connexion

Cette implémentation révisée garantit que le sémaphore est publié avant la suppression du dictionnaire, éliminant ainsi la condition de concurrence critique et résolvant les erreurs intermittentes d'accès aux fichiers.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal