Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 清理NameDrawerWriterLocker中未使用的锁_C#_Multithreading_Asynchronous_Thread Safety_Locking - Fatal编程技术网

C# 清理NameDrawerWriterLocker中未使用的锁

C# 清理NameDrawerWriterLocker中未使用的锁,c#,multithreading,asynchronous,thread-safety,locking,C#,Multithreading,Asynchronous,Thread Safety,Locking,对于异步文件IO,我创建了一个类,它允许我基于字符串键进行锁定,以防止对同一文件同时进行多次写入,或防止同时进行写入和读取。然而,我面临的问题是,通过每次发送不同的密钥,可能会增加锁的大小。旧的未使用的锁没有清理,但我不知道如何以线程安全的方式进行清理。这可能会导致非常大的内存消耗 基于密钥返回锁实例的类: public class AsyncNamedReaderWriterLocker { private readonly object _mutex = new object

对于异步文件IO,我创建了一个类,它允许我基于字符串键进行锁定,以防止对同一文件同时进行多次写入,或防止同时进行写入和读取。然而,我面临的问题是,通过每次发送不同的密钥,可能会增加锁的大小。旧的未使用的锁没有清理,但我不知道如何以线程安全的方式进行清理。这可能会导致非常大的内存消耗

基于密钥返回锁实例的类:

    public class AsyncNamedReaderWriterLocker
{
    private readonly object _mutex = new object();
    private readonly Dictionary<string, AsyncReaderWriterLock> _lockDict = new Dictionary<string, AsyncReaderWriterLock>();

    public Task<IDisposable> EnterReaderLockAsync(string name)
    {
        var locker = GetLock(name);
        return locker.EnterReaderLockAsync();
    }

    public Task<IDisposable> EnterWriterLockAsync(string name)
    {
        var locker = GetLock(name);
        return locker.EnterWriterLockAsync();
    }

    private AsyncReaderWriterLock GetLock(string name)
    {
        lock (_mutex)
        {
            if (!_lockDict.TryGetValue(name, out AsyncReaderWriterLock locker))
            {
                locker = new AsyncReaderWriterLock();
                _lockDict.Add(name, locker);
            }
            return locker;
        }
    }
公共类AsyncNameDrawerWriterLocker
{
私有只读对象_mutex=新对象();
专用只读词典_lockDict=新词典();
公共任务EnterReaderLockAsync(字符串名称)
{
var locker=GetLock(名称);
return locker.entreReaderLockAsync();
}
公共任务EnterWriterLockAsync(字符串名称)
{
var locker=GetLock(名称);
return locker.EnterWriterLockAsync();
}
专用AsyncReaderWriterLock GetLock(字符串名称)
{
锁(互斥)
{
if(!\u lockDict.TryGetValue(名称,out AsyncReaderWriterLocker))
{
locker=新的AsyncReaderWriterLock();
_添加(姓名、储物柜);
}
返回储物柜;
}
}
锁本身(创意来源:):

公共类AsyncReaderWriterLock
{
私有只读队列_writerQueue=新队列();
私有只读队列_readerQueue=new Queue();
专用只读WriterLocker\u WriterLocker;
专用只读读卡器\u读卡器;
私有只读对象_mutex=新对象();
私人国际洛克谢尔德酒店;
公共AsyncReaderWriterLock()
{
_writerLocker=新的writerLocker(此);
_readerLocker=新的readerLocker(此);
}
公共任务EnterReaderLockAsync()
{
锁(互斥)
{
如果(_locksHeld>=0&&u writerQueue.Count==0)
{
_locksHeld++;
返回Task.FromResult(_readerLocker);
}
var tcs=new TaskCompletionSource();
_readerQueue.Enqueue(tcs);
返回tcs.Task;
}
}
公共任务EnterWriterLockAsync()
{
锁(互斥)
{
如果(_locksHeld==0)
{
_locksHeld=-1;
返回Task.FromResult(_writerLocker);
}
var tcs=new TaskCompletionSource();
_writerQueue.Enqueue(tcs);
返回tcs.Task;
}
}
私有无效释放锁()
{
如果(_locksHeld!=0)
回来
//优先考虑作家。
如果(_writerQueue.Count!=0)
{
_locksHeld=-1;
var tcs=_writerQueue.Dequeue();
tcs.TrySetResult(_writerLocker);
回来
}
//然后给读者。
而(_readerQueue.Count!=0)
{
var tcs=_readerQueue.Dequeue();
tcs.TrySetResult(_readerLocker);
++_洛克谢尔德;
}
}
私有void ReleaseReaderLock()
{
锁(互斥)
{
_洛克谢尔德;
释放锁();
}
}
私有void ReleaseWriterLock()
{
锁(互斥)
{
_locksHeld=0;
释放锁();
}
}
私有类ReaderLocker:IDisposable
{
私有只读AsyncReaderWriterLock\u AsyncReaderWriterLock;
内部ReaderLocker(AsyncReaderWriterLock AsyncReaderWriterLock)
{
_asyncReaderWriterLock=asyncReaderWriterLock;
}
公共空间处置()
{
_asyncReaderWriterLock.ReleaseReaderLock();
}
}
私有类WriterLocker:IDisposable
{
私有只读AsyncReaderWriterLock\u AsyncReaderWriterLock;
内部WriterLocker(AsyncReaderWriterLock AsyncReaderWriterLock)
{
_asyncReaderWriterLock=asyncReaderWriterLock;
}
公共空间处置()
{
_asyncReaderWriterLock.ReleaseWriterLock();
}
}
}
使用AsyncNameDrawerWriterLocker类的示例:

    public class AsyncFileIO
{
    private static readonly AsyncNamedReaderWriterLocker AsyncNamedReaderWriterLocker = new AsyncNamedReaderWriterLocker();

    public async Task CreateFile(string filename, byte[] data)
    {
        using (await AsyncNamedReaderWriterLocker.EnterWriterLockAsync(filename))
        {
            var directory = Path.GetDirectoryName(filename);
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }
            using (var stream = File.Create(filename))
            {
                await stream.WriteAsync(data, 0, data.Length);
            }
        }
    }

    public async Task<byte[]> ReadFile(string filename)
    {
        using (await AsyncNamedReaderWriterLocker.EnterReaderLockAsync(filename))
        {
            if (!File.Exists(filename)) return null;
            using (var stream = File.OpenRead(filename))
            {
                var data = new byte[stream.Length];
                await stream.ReadAsync(data, 0, 0);
                return data;
            }
        }
    }

    public async Task DeleteFile(string filename)
    {
        using (await AsyncNamedReaderWriterLocker.EnterWriterLockAsync(filename))
        {
            var directoryName = Path.GetDirectoryName(filename);
            if (!Directory.Exists(directoryName)) return;
            File.Delete(filename);
        }
    }
}
公共类AsyncFileIO
{
私有静态只读AsyncNameDrawerWriterLocker AsyncNameDrawerWriterLocker=新的AsyncNameDrawerWriterLocker();
公共异步任务CreateFile(字符串文件名,字节[]数据)
{
使用(等待AsyncNameDrawerWriterLocker.EnterWriterLockAsync(文件名))
{
var directory=Path.GetDirectoryName(文件名);
如果(!Directory.Exists(Directory))
{
CreateDirectory(目录);
}
使用(var stream=File.Create(文件名))
{
wait stream.WriteAsync(数据,0,数据.长度);
}
}
}
公共异步任务读取文件(字符串文件名)
{
使用(等待AsyncNameDrawerWriterLocker.EnterReaderLockAsync(文件名))
{
如果(!File.Exists(filename))返回null;
使用(var stream=File.OpenRead(文件名))
{
var data=新字节[stream.Length];
wait stream.ReadAsync(数据,0,0);
返回数据;
}
}
}
公共异步任务删除文件(字符串文件名)
{
使用(等待AsyncNameDrawerWriterLocker.EnterWriterLockAsync(文件名))
{
var directoryName=Path.GetDirectoryName(文件名);
如果(!Directory.Exists(directoryName))返回;
删除(文件名);
}
}
}

请注意,出于学习目的,我对此非常感兴趣,并充分意识到这对于大多数应用程序来说都是过分的。

起初,我在尝试同步时遇到了死锁
    public class AsyncFileIO
{
    private static readonly AsyncNamedReaderWriterLocker AsyncNamedReaderWriterLocker = new AsyncNamedReaderWriterLocker();

    public async Task CreateFile(string filename, byte[] data)
    {
        using (await AsyncNamedReaderWriterLocker.EnterWriterLockAsync(filename))
        {
            var directory = Path.GetDirectoryName(filename);
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }
            using (var stream = File.Create(filename))
            {
                await stream.WriteAsync(data, 0, data.Length);
            }
        }
    }

    public async Task<byte[]> ReadFile(string filename)
    {
        using (await AsyncNamedReaderWriterLocker.EnterReaderLockAsync(filename))
        {
            if (!File.Exists(filename)) return null;
            using (var stream = File.OpenRead(filename))
            {
                var data = new byte[stream.Length];
                await stream.ReadAsync(data, 0, 0);
                return data;
            }
        }
    }

    public async Task DeleteFile(string filename)
    {
        using (await AsyncNamedReaderWriterLocker.EnterWriterLockAsync(filename))
        {
            var directoryName = Path.GetDirectoryName(filename);
            if (!Directory.Exists(directoryName)) return;
            File.Delete(filename);
        }
    }
}
    public class NamedAsyncReaderWriterLockController<TKey>
{
    private readonly object _mutex = new object();
    private readonly Dictionary<TKey, NamedAsyncReaderWriterLock> _lockDict = new Dictionary<TKey, NamedAsyncReaderWriterLock>();


    public Task<IDisposable> EnterReaderLockAsync(TKey name)
    {
        lock (_mutex)
        {
            var locker = GetLock(name);
            return locker.EnterReaderLockAsync();
        }
    }

    public Task<IDisposable> EnterWriterLockAsync(TKey name)
    {
        lock (_mutex)
        {
            var locker = GetLock(name);
            return locker.EnterWriterLockAsync();
        }
    }

    private NamedAsyncReaderWriterLock GetLock(TKey name)
    {
        NamedAsyncReaderWriterLock locker;
        if (!_lockDict.TryGetValue(name, out locker))
        {
            locker = new NamedAsyncReaderWriterLock(this, name, _mutex);
            _lockDict.Add(name, locker);
        }
        return locker;
    }

    private void RemoveLock(TKey name)
    {
        _lockDict.Remove(name);
    }

    private class NamedAsyncReaderWriterLock
    {
        private readonly TKey _name;
        private readonly NamedAsyncReaderWriterLockController<TKey> _namedAsyncReaderWriterLockController;
        private readonly Queue<TaskCompletionSource<IDisposable>> _writerQueue = new Queue<TaskCompletionSource<IDisposable>>();
        private readonly Queue<TaskCompletionSource<IDisposable>> _readerQueue = new Queue<TaskCompletionSource<IDisposable>>();
        private readonly NamedWriterLock _namedWriterLock;
        private readonly NamedReaderLock _namedReaderLock;
        private readonly object _mutex = new object();
        private readonly object _releaseMutex;
        private int _locksHeld;

        public NamedAsyncReaderWriterLock(NamedAsyncReaderWriterLockController<TKey> namedAsyncReaderWriterLockController, TKey name, object releaseMutex)
        {
            _namedWriterLock = new NamedWriterLock(this);
            _namedReaderLock = new NamedReaderLock(this);
            _releaseMutex = releaseMutex;
            _name = name;
            _namedAsyncReaderWriterLockController = namedAsyncReaderWriterLockController;
        }

        public Task<IDisposable> EnterReaderLockAsync()
        {
            lock (_mutex)
            {
                if (_locksHeld >= 0 && _writerQueue.Count == 0)
                {
                    _locksHeld++;
                    return Task.FromResult<IDisposable>(_namedReaderLock);
                }
                var tcs = new TaskCompletionSource<IDisposable>();
                _readerQueue.Enqueue(tcs);
                return tcs.Task;
            }
        }

        public Task<IDisposable> EnterWriterLockAsync()
        {
            lock (_mutex)
            {
                if (_locksHeld == 0)
                {
                    _locksHeld = -1;
                    return Task.FromResult<IDisposable>(_namedWriterLock);
                }
                var tcs = new TaskCompletionSource<IDisposable>();
                _writerQueue.Enqueue(tcs);
                return tcs.Task;
            }
        }

        private void ReleaseLocks()
        {
            if (_locksHeld != 0)
                return;

            // Give priority to writers.
            if (_writerQueue.Count != 0)
            {
                _locksHeld = -1;
                var tcs = _writerQueue.Dequeue();
                tcs.TrySetResult(_namedWriterLock);
                return;
            }

            // Then to readers.
            while (_readerQueue.Count != 0)
            {
                var tcs = _readerQueue.Dequeue();
                tcs.TrySetResult(_namedReaderLock);
                ++_locksHeld;
            }

            if (_locksHeld == 0) _namedAsyncReaderWriterLockController.RemoveLock(_name);
        }

        private void ReleaseReaderLock()
        {
            lock (_releaseMutex)
            {
                lock (_mutex)
                {
                    _locksHeld--;
                    ReleaseLocks();
                }
            }
        }

        private void ReleaseWriterLock()
        {
            lock (_releaseMutex)
            {
                lock (_mutex)
                {
                    _locksHeld = 0;
                    ReleaseLocks();
                }
            }
        }

        private class NamedReaderLock : IDisposable
        {
            private readonly NamedAsyncReaderWriterLock _namedAsyncReaderWriterLock;

            internal NamedReaderLock(NamedAsyncReaderWriterLock namedAsyncReaderWriterLock)
            {
                _namedAsyncReaderWriterLock = namedAsyncReaderWriterLock;
            }

            public void Dispose()
            {
                _namedAsyncReaderWriterLock.ReleaseReaderLock();
            }
        }

        private class NamedWriterLock : IDisposable
        {
            private readonly NamedAsyncReaderWriterLock _namedAsyncReaderWriterLock;

            internal NamedWriterLock(NamedAsyncReaderWriterLock namedAsyncReaderWriterLock)
            {
                _namedAsyncReaderWriterLock = namedAsyncReaderWriterLock;
            }

            public void Dispose()
            {
                _namedAsyncReaderWriterLock.ReleaseWriterLock();
            }
        }
    }