I have a factory which job is to create new instances on each call when such are needed. My code looks like that:
public class Factory
{
public object Get()
=> new object();
}
I try testing the multi threading part with such nunit test:
public async Task Get_ThreadSaftyTests()
{
const int limit = 10_000
var concurrentCollection = new ConcurrentBag<object>();
var instance = new Factory();
var tasks = new List<Task>(limit);
for (int i = 0; i < limit; i++)
{
tasks.Add(Task.Factory.StartNew(() =>
{
concurrentCollection.Add(instance.Get());
}));
}
await Task.WhenAll(tasks);
var hashSet = new HashSet<long>();
foreach (var item in concurrentCollection)
{
hashSet.Add(item.GetHashCode());
}
Assert.AreEqual(limit, hashSet.Count);
}
This test passes most of the time. 4/5 to be exact. Which is a bit strange.
I have tried to implement a lock on before returning the instance like so:
public class Factory
{
private static readonly Lazy<object> lockObject = new Lazy<object>(true);
public object Get()
{
lock (lockObject.Value)
{
return new object();
}
}
}
but with that implementation the test almost never passes. 1/5 runs the test passes. The question here is what am i doing wrong?
------------------------------update-------------------------------
If the loop has 100 000 iterations the test fails every time in both cases.
If the loop has 6 500 iterations it passes every time in both cases.