So, I don't have a lot of experience dealing with concurrent problems so I've decided to ask a question, regarding a piece of code.
I have class:
public class SimpleClass
{
public int OwnNumber { get; set; }
public int ActualNumber { get; set; }
}
there are two extension methods working with this class:
public static class SimpleClassHelper
{
public static int Apply(this SimpleClass sc)
{
int z = 1;
for (var i = 0; i < 1000; i++)
{
z += i;
}
return sc.ActualNumber;
}
public static IEnumerable<SimpleClass> Test(this IEnumerable<SimpleClass> sc) =>
sc.AsParallel().Select(s => new SimpleClass
{
OwnNumber = s.OwnNumber,
ActualNumber = s.Apply()
});
}
and in my Program.cs I have this:
static void Main(string[] args)
{
var s = new SimpleClass { OwnNumber = 0, ActualNumber = 0 };
var s1 = new SimpleClass { OwnNumber = 1, ActualNumber = 1 };
var s2 = new SimpleClass { OwnNumber = 2, ActualNumber = 2 };
var s3 = new SimpleClass { OwnNumber = 3, ActualNumber = 3 };
var s4 = new SimpleClass { OwnNumber = 4, ActualNumber = 4 };
var s5 = new SimpleClass { OwnNumber = 5, ActualNumber = 5 };
var s6 = new SimpleClass { OwnNumber = 6, ActualNumber = 6 };
var s7 = new SimpleClass { OwnNumber = 7, ActualNumber = 7 };
List<SimpleClass> seq = new List<SimpleClass>();
seq.Add(s);
seq.Add(s1);
seq.Add(s2);
seq.Add(s3);
seq.Add(s4);
seq.Add(s5);
seq.Add(s6);
seq.Add(s7);
for (var i = 0; i < 10; i++)
{
var res = seq.Test();
foreach (var item in res)
{
Console.WriteLine($"{item.OwnNumber} : {item.ActualNumber}");
}
}
}
The code is a bit too much but it's a fully working example and I think, it quite well displays my confusion.
My train of thought is this:
- I create a collection
seq
- I call 10 times
Test()
on this collection - Each time I call
Test
the collection is separated into several chunks executed in parallel - At some point when I apply the value from
s.Apply()
I expect that at least some percentage of the time the reference in theApply()
method will be replaced with reference with from some of the parallel threads and I will get differentOwnNumber
andActualNumber
.
However I made several runs and everything seems to be in order but with concurrency you never know. Is this an expected behavior of AsParalle()
? Since all objects are calling the same Apply()
method why I never see the behavior described above? If, say, 3 threads are calling Apply()
at the same time I expect at least at several points to get the value from some other object especially since I have some delay with the for loop?
Well, it seems that maybe I'm wrong in my assumptions but then is there something preveting this code from race conditions?