我正在尝试同步将要提供图像的webapi。当我请求一个特定的图像时,它将检查图像是否已经存在并返回它,如果它不存在,或者它不存在它将创建它然后返回它。
我的问题是它显然不像那样是线程安全的;我有一个线程进来确定图像不存在并开始创建它,而另一个请求进来,并确定图像不存在(刚刚)并尝试创建它。我知道我可以锁定整个事情以避免这个问题,但我试图避免这一点。将有10万个图像,我不明白为什么我需要阻止所有线程读取其他图像只是因为还没有一个图像。这样做有“通常”的方法吗? ID是否请求图像,我可以锁定特定图像的ID吗?例如
List<long> _locks = new List<long>();
_locks.Add(17);
lock(_locks[0]){...}
看起来不对......当然有更好的解决方案吗?
答案 0 :(得分:2)
这取决于您的服务器设置(单个或服务器场)。在单个服务器上,您可以使用共享HashSet。文件名是一个很好的关键。你只需要在Set周围设置一个短锁,这不会影响性能。
以下是关于concurrent HashSet
的问题答案 1 :(得分:0)
我的朋友,你想避免“基于尝试”的方法,你想避免“锁定”的方法,然而,你访问共享资源。尝试在任何托管dll上调用corflags
并保持命令窗口。然后转到Windows资源管理器并尝试删除该文件。你会得到“文件正在使用中”。即使是Windows也不是完全脱离了文件,而是它的所有缓存机制。当然,问题是你有所有文件都通过相同的锁。也许你可以做些什么来减少这种情况。让我们来看看。这是完全没有经过考验的想法:
创建自定义锁定对象
public class CustomLock
{
private object _lock = new object();
private string _file;
public CustomLock(string file)
{_file = file;}
public object Read()
{
lock(_lock)
{
// read your file
}
}
public object Read()
{
lock(_lock)
{
// read your file
}
}
public override int GetHashCode()
{
// here your hash algorithm
}
}
现在,使用HashTable
与此http://msdn.microsoft.com/en-us/library/system.collections.hashtable.synchronized%28v=vs.110%29.aspx所述的HashTable.Synchronized
一起使用锁定缓存
或者您可以同步词典What's the best way of implementing a thread-safe Dictionary?。所以,现在它会是这样的:
var custLock = GetCustLock(file); // This should always return CustomLock object, new or existing
object file = custLock.Read();
据推测,使用此设计,您将消除在同一位置锁定所有文件的瓶颈。请测试一下。