Rumah >pembangunan bahagian belakang >C++ >Mengapakah penguncian tak segerak berdasarkan kunci menyebabkan ralat capaian fail terputus-putus, dan bagaimanakah pendekatan pengiraan rujukan boleh memperbaikinya?
Penguncian Berasaskan Kunci Tak Segerak: Sumber Ralat Akses Fail Berselang-seli
Mekanisme cache pustaka ImageProcessor, menggunakan penguncian tak segerak berdasarkan kekunci, mengalami ralat akses fail yang terputus-putus. Ini berpunca daripada kecacatan reka bentuk dalam kelas AsyncDuplicateLock
.
Kecacatan: Pelepasan Semaphore Pramatang
Kod AsyncDuplicateLock
asal mengalih keluar tika SemaphoreSlim
daripada ConcurrentDictionary
sebelum mengeluarkan semaphore. Ini membawa kepada churn semaphore yang berlebihan dan kemungkinan ralat kerana semaphore mungkin boleh diakses selepas dialih keluar.
Penyelesaian: Pendekatan Pengiraan Rujukan Teguh
Penyelesaian unggul menggunakan pengiraan rujukan. Setiap semafor dalam kamus mengekalkan kiraan rujukan. Kunci tunggal menjamin atomicity untuk mengurangkan kiraan dan mengeluarkan semafor, menghapuskan keperluan untuk 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>
Pendekatan yang disemak ini menjamin semaphore dikeluarkan hanya apabila tidak diperlukan lagi, dengan berkesan menghalang ralat akses fail terputus-putus semasa operasi cache.
Atas ialah kandungan terperinci Mengapakah penguncian tak segerak berdasarkan kunci menyebabkan ralat capaian fail terputus-putus, dan bagaimanakah pendekatan pengiraan rujukan boleh memperbaikinya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!