gpt4 book ai didi

c# - 通过字符串锁定。这安全/理智吗?

转载 作者:IT王子 更新时间:2023-10-29 04:14:44 26 4
gpt4 key购买 nike

我需要通过字符串锁定一段代码。当然,以下代码非常不安全:

lock("http://someurl")
{
//bla
}

所以我一直在想出一个替代方案。我通常不会在这里发布大量代码,但是当涉及到并发编程时,我对制定自己的同步方案有点担心,所以我提交我的代码来询问这样做是否明智以这种方式或是否有更直接的方法。

public class StringLock
{
private readonly Dictionary<string, LockObject> keyLocks = new Dictionary<string, LockObject>();
private readonly object keyLocksLock = new object();

public void LockOperation(string url, Action action)
{
LockObject obj;
lock (keyLocksLock)
{
if (!keyLocks.TryGetValue(url,
out obj))
{
keyLocks[url] = obj = new LockObject();
}
obj.Withdraw();
}
Monitor.Enter(obj);
try
{
action();
}
finally
{
lock (keyLocksLock)
{
if (obj.Return())
{
keyLocks.Remove(url);
}
Monitor.Exit(obj);
}
}
}

private class LockObject
{
private int leaseCount;

public void Withdraw()
{
Interlocked.Increment(ref leaseCount);
}

public bool Return()
{
return Interlocked.Decrement(ref leaseCount) == 0;
}
}
}

我会这样使用它:

StringLock.LockOperation("http://someurl",()=>{
//bla
});

好走,还是崩溃和燃烧?

编辑

为了后代,这是我的工作代码。感谢所有建议:

public class StringLock
{
private readonly Dictionary<string, LockObject> keyLocks = new Dictionary<string, LockObject>();
private readonly object keyLocksLock = new object();

public IDisposable AcquireLock(string key)
{
LockObject obj;
lock (keyLocksLock)
{
if (!keyLocks.TryGetValue(key,
out obj))
{
keyLocks[key] = obj = new LockObject(key);
}
obj.Withdraw();
}
Monitor.Enter(obj);
return new DisposableToken(this,
obj);
}

private void ReturnLock(DisposableToken disposableLock)
{
var obj = disposableLock.LockObject;
lock (keyLocksLock)
{
if (obj.Return())
{
keyLocks.Remove(obj.Key);
}
Monitor.Exit(obj);
}
}

private class DisposableToken : IDisposable
{
private readonly LockObject lockObject;
private readonly StringLock stringLock;
private bool disposed;

public DisposableToken(StringLock stringLock, LockObject lockObject)
{
this.stringLock = stringLock;
this.lockObject = lockObject;
}

public LockObject LockObject
{
get
{
return lockObject;
}
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

~DisposableToken()
{
Dispose(false);
}

private void Dispose(bool disposing)
{
if (disposing && !disposed)
{
stringLock.ReturnLock(this);
disposed = true;
}
}
}

private class LockObject
{
private readonly string key;
private int leaseCount;

public LockObject(string key)
{
this.key = key;
}

public string Key
{
get
{
return key;
}
}

public void Withdraw()
{
Interlocked.Increment(ref leaseCount);
}

public bool Return()
{
return Interlocked.Decrement(ref leaseCount) == 0;
}
}
}

使用如下:

var stringLock=new StringLock();
//...
using(stringLock.AcquireLock(someKey))
{
//bla
}

最佳答案

通过任意字符串实例锁定不是一个好主意,因为 Monitor.Lock 会锁定该实例。如果您有两个具有相同内容的不同字符串实例,那将是两个独立的锁,这是您不想要的。所以您对任意字符串的关注是正确的。

但是,.NET 已经有一个内置机制来返回给定字符串内容的“规范实例”:String.Intern .如果您将两个具有相同内容的不同字符串实例传递给它,您将两次返回相同的结果实例。

lock (string.Intern(url)) {
...
}

这个比较简单;供您测试的代码更少,因为您将依赖于框架中已有的内容(大概已经可以工作了)。

关于c# - 通过字符串锁定。这安全/理智吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4224888/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com