Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Equivalent of Array in Concurrent Collections

I have the following process in a Single Thread Environment:

int[] ages = { 40, 30, 18, 23, 60, 24 };
for (int i = 0; i < ages.Length; i++)
{
    if (ages[i] < 21) ages[i] = 0;
}

As an example, but now I want to do this process in a Multi Thread Environment. Is there a Concurrent collection simulate an array in multi threading environment?

like image 668
Josbel Luna Avatar asked Jan 03 '23 13:01

Josbel Luna


2 Answers

Closest solution is to use ConcurrentDictionary using the index as the key. The hash function will be really good in this case:

var dict = new ConcurrentDictionary<int, int>(Enumerable.Range(0, ages.Length).ToDictionary(i => i, i => ages[i]));
Parallel.For(0, dict.Count,
    i =>
    {
        int value;
        if (dict.TryGetValue(i, out value) && value < 21)
            dict.TryUpdate(i, value, 0);
    });

Pay attention to the fact that this particular example doesn't need to use ConcurrentDictionary at all because you have no dependency between each iteration.

Parallel.For(0, ages.Length,
    i =>
    {
        if (ages[i] < 21) ages[i] = 0;
    });

This code will perfectly work for your example. Next time use something more complex like the sum of the array elements.

Hope this help!

like image 147
Miguel Avatar answered Jan 11 '23 06:01

Miguel


You can try using Parallel Linq (PLinq) and let .Net materialize the final result as an array; in your case:

 int[] ages = { 40, 30, 18, 23, 60, 24 };

 ages = ages
   .AsParallel()
   .Select(age => age < 21 ? 0 : age)
   .ToArray(); 

The advantage of PLinq is that .Net is responsible for the inner collections choice, locking etc. If you want, say, find an average age in parallel all you have to do is to slightly edit the query:

 var averageAge = ages
   .AsParallel()
   .Average();
like image 21
Dmitry Bychenko Avatar answered Jan 11 '23 08:01

Dmitry Bychenko