有没有办法在C#中锁定一个整数?整数不能与锁一起使用,因为它们是盒装的(并且只锁定引用上的锁).
场景如下:我有一个基于论坛的网站,具有审核功能.我想要做的是确保在任何给定时间不超过一个主持人可以调节帖子.为此,我想锁定帖子的ID.
到目前为止我有几个想法(例如使用字典<int,object>),但我正在寻找一种更好,更清洁的方法.
有什么建议?
con*_*tor 26
我喜欢这样做
public class Synchronizer {
private Dictionary<int, object> locks;
private object myLock;
public Synchronizer() {
locks = new Dictionary<int, object>();
myLock = new object();
}
public object this[int index] {
get {
lock (myLock) {
object result;
if (locks.TryGetValue(index, out result))
return result;
result = new object();
locks[index] = result;
return result;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,简单地锁定一个int(每次使用相同的同步器)
lock (sync[15]) { ... }
Run Code Online (Sandbox Code Playgroud)
当给出相同的索引两次时,此类返回相同的锁对象.当一个新索引到来时,它会创建一个对象,返回它,然后将它存储在字典中以供下次使用.
它可以很容易地更改为使用任何struct或值类型一般工作,或者static使得不必传递同步器对象.
如果它是一个网站,那么使用进程内锁可能不是最好的方法,就好像你需要将网站扩展到多个服务器,或添加另一个托管API的网站(或任何其他需要其他进程访问相同的网站)数据存在)然后你所有的锁定策略立即无效.
我倾向于研究基于数据库的锁定.最简单的方法是使用乐观锁定,例如上次更新帖子的时间戳,以及拒绝对帖子进行的更新,除非时间戳匹配.
我已经阅读了很多评论,提到锁定对Web应用程序来说并不安全,但除了Web场之外,我还没有看到任何解释原因.我有兴趣听取反对它的论点.
我有类似的需求,虽然我在硬盘上缓存重新调整大小的图像(这显然是一个本地操作,因此Web场景不是问题).
这是@Configurator发布的重做版本.它包含一些@Configurator不包含的功能:
这是代码......
/// <summary>
/// Provides a way to lock a resource based on a value (such as an ID or path).
/// </summary>
public class Synchronizer<T>
{
private Dictionary<T, SyncLock> mLocks = new Dictionary<T, SyncLock>();
private object mLock = new object();
/// <summary>
/// Returns an object that can be used in a lock statement. Ex: lock(MySync.Lock(MyValue)) { ... }
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public SyncLock Lock(T value)
{
lock (mLock)
{
SyncLock theLock;
if (mLocks.TryGetValue(value, out theLock))
return theLock;
theLock = new SyncLock(value, this);
mLocks.Add(value, theLock);
return theLock;
}
}
/// <summary>
/// Unlocks the object. Called from Lock.Dispose.
/// </summary>
/// <param name="theLock"></param>
public void Unlock(SyncLock theLock)
{
mLocks.Remove(theLock.Value);
}
/// <summary>
/// Represents a lock for the Synchronizer class.
/// </summary>
public class SyncLock
: IDisposable
{
/// <summary>
/// This class should only be instantiated from the Synchronizer class.
/// </summary>
/// <param name="value"></param>
/// <param name="sync"></param>
internal SyncLock(T value, Synchronizer<T> sync)
{
Value = value;
Sync = sync;
}
/// <summary>
/// Makes sure the lock is removed.
/// </summary>
public void Dispose()
{
Sync.Unlock(this);
}
/// <summary>
/// Gets the value that this lock is based on.
/// </summary>
public T Value { get; private set; }
/// <summary>
/// Gets the synchronizer this lock was created from.
/// </summary>
private Synchronizer<T> Sync { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
这是你如何使用它...
public static readonly Synchronizer<int> sPostSync = new Synchronizer<int>();
....
using(var theLock = sPostSync.Lock(myID))
lock (theLock)
{
...
}
Run Code Online (Sandbox Code Playgroud)
为什么不锁定整个帖子而只锁定其 ID?
| 归档时间: |
|
| 查看次数: |
19072 次 |
| 最近记录: |