I need a synchronization mechanism to allow only one unique item to be proceeded concurrently. So I used Monitor.Enter to block other concurrent execution on the same item.
Here is a cutted version of my code and its unit test to validate the logic.
But I see that some items in my collection can acquire the lock from Monitor.Enter more than one which shouldn't be occured because I don't release the lock when any item is get.
Why I see some of the item in currencies collection has 2 or sometimes 3 as value?
[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]);
}
}
}