> 백엔드 개발 > C++ > 키를 기반으로 한 비동기식 잠금이 간헐적인 파일 액세스 오류를 일으키는 이유는 무엇이며 참조 계산 방식을 통해 이를 어떻게 개선할 수 있습니까?

키를 기반으로 한 비동기식 잠금이 간헐적인 파일 액세스 오류를 일으키는 이유는 무엇이며 참조 계산 방식을 통해 이를 어떻게 개선할 수 있습니까?

Susan Sarandon
풀어 주다: 2025-01-15 09:35:43
원래의
238명이 탐색했습니다.

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿