我需要一种同步机制,只允许一个唯一的项同时进行。所以我使用Monitor.Enter阻止同一项上的其他并发执行。
以下是我的代码的切割版本及其验证逻辑的单元测试。
但是我看到我的收藏中的一些项目可以从Monitor.Enter获取多个不应该发生的锁,因为我没有在任何项目获得时释放锁。
为什么我看到货币集合中的某些项目有2个或有时3个作为值?
[TestClass]
public class UnitTest2
{
public static ConcurrentDictionary<string, object> _keyLocks =
new ConcurrentDictionary<string, object>();
public static object AcquireLock(string item)
{
object obj = _keyLocks.GetOrAdd(item, new object());
Monitor.Enter(obj);
}
[TestMethod]
public void AcquireLock_MultipleRequest_OnlyAllow1Request()
{
Dictionary<string, int> currencies = new Dictionary<string, int>() {
{ "USD",0 },
{ "EUR",0 },
{ "TRY",0 },
{ "AUD",0 },
{ "PLN",0 }
};
int totalTask = 1000;
List<Task> tasks = new List<Task>();
for (int i = 0; i < totalTask; i++)
{
string curr = currencies.Keys.ElementAt(i % currencies.Count);
tasks.Add(Task.Factory.StartNew((obj) =>
{
string currStr = (string)obj;
AcquireLock(currStr);
currencies[currStr] += 1;
//Monitor.Exit will be implemented
}, curr));
}
Thread.Sleep(10000);
foreach (var item in currencies.Keys)
{
Assert.AreEqual(1, currencies[item]);
}
}
}
答案 0 :(得分:1)
为什么我看到货币集合中的某些项目有2个或有时3个作为值?
因为您正在使用线程池来获取锁。使用线程池意味着可以在同一线程中执行多个操作,当然,基于每个线程获取对象的监视器。即给定的线程可以多次获取同一个锁。
还要将您问题中发布的评论牢记在心。您正在以混乱,冗余的方式混合同步机制。