Maison >développement back-end >C++ >Comment résoudre les erreurs d'accès intermittent aux fichiers dans le verrouillage asynchrone ?
Verrouillage asynchrone par clé
Cet article traite d'un problème rencontré dans la bibliothèque ImageProcessor : une erreur intermittente d'accès aux fichiers lors de l'ajout du cache. Le message d'erreur indique que le fichier en question est utilisé par un autre processus. Pour résoudre ce problème, un mécanisme de verrouillage asynchrone basé sur une clé est mis en œuvre. Cependant, il a été découvert plus tard que cette mise en œuvre comportait un oubli.
Le problème
La classe de verrouillage d'origine AsyncDuplicateLock
tente d'effectuer un verrouillage asynchrone en récupérant le sémaphore du dictionnaire concurrent à l'aide de la clé. Cependant, il supprime par erreur le sémaphore du dictionnaire avant de le publier. Cela signifie que le sémaphore a été supprimé alors qu'il était encore en cours d'utilisation, ce qui a entraîné l'erreur d'accès au fichier observée.
Solution
Pour résoudre ce problème, la classe de verrouillage a été modifiée. Au lieu d'utiliser une approche simultanée sans verrouillage basée sur un dictionnaire, la version mise à jour utilise une approche plus traditionnelle qui combine le comptage de références et un verrou unique. Cela garantit que les sémaphores ne sont libérés que lorsqu'ils ne sont plus utilisés.
Voici le code de classe de verrouillage modifié :
<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>
Cette implémentation mise à jour maintient un décompte de références pour chaque sémaphore et garantit que le sémaphore n'est supprimé du dictionnaire que lorsque plus aucun verrou actif n'y fait référence. Cette approche résout efficacement les erreurs intermittentes d’accès aux fichiers rencontrées dans les implémentations précédentes.
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!