I've been trying to solve this issue for quite some time now. I've written some example code showcasing the usage of lock in C#. Running my code manually I can see that it works the way it should, but of course I would like to write a unit test that confirms my code.
I have the following ObjectStack.cs class:
enum ExitCode { Success = 0, Error = 1 } public class ObjectStack { private readonly Stack<Object> _objects = new Stack<object>(); private readonly Object _lockObject = new Object(); private const int NumOfPopIterations = 1000; public ObjectStack(IEnumerable<object> objects) { foreach (var anObject in objects) { Push(anObject); } } public void Push(object anObject) { _objects.Push(anObject); } public void Pop() { _objects.Pop(); } public void ThreadSafeMultiPop() { for (var i = 0; i < NumOfPopIterations; i++) { lock (_lockObject) { try { Pop(); } //Because of lock, the stack will be emptied safely and no exception is ever caught catch (InvalidOperationException) { Environment.Exit((int)ExitCode.Error); } if (_objects.Count == 0) { Environment.Exit((int)ExitCode.Success); } } } } public void ThreadUnsafeMultiPop() { for (var i = 0; i < NumOfPopIterations; i++) { try { Pop(); } //Because there is no lock, an exception is caught when popping an already empty stack catch (InvalidOperationException) { Environment.Exit((int)ExitCode.Error); } if (_objects.Count == 0) { Environment.Exit((int)ExitCode.Success); } } } } And Program.cs:
public class Program { private const int NumOfObjects = 100; private const int NumOfThreads = 10000; public static void Main(string[] args) { var objects = new List<Object>(); for (var i = 0; i < NumOfObjects; i++) { objects.Add(new object()); } var objectStack = new ObjectStack(objects); Parallel.For(0, NumOfThreads, x => objectStack.ThreadUnsafeMultiPop()); } } I'm trying to write a unit that tests the thread unsafe method, by checking the exit code value (0 = success, 1 = error) of the executable.
I tried to start and run the application executable as a process in my test, a couple of 100 times, and checked the exit code value each time in the test. Unfortunately, it was 0 every single time.
Any ideas are greatly appreciated!
ConcurrentStack?Mainyou only create 100 of objects inforloop, and then you are trying to pop out 100 items with 10000 threads? They all emptied by first thread alone.ConcurrentStackis not used because the point here is to illustrate the usage oflockin concurrent code.