-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathConcurrentDictionaryCollectionDemo.cs
More file actions
121 lines (105 loc) · 3.7 KB
/
ConcurrentDictionaryCollectionDemo.cs
File metadata and controls
121 lines (105 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
// Demo of using concurrent dictionary
namespace ConcurrentDictionaryCollectionDemo
{
public class Program
{
static void Main(string[] args)
{
var toProcess = new ConcurrentQueue<char>();
var letterFreq = new ConcurrentDictionary<char, int>();
var tasks = new[]
{
Task.Run(() => ProduceLetters(toProcess)),
Task.Run(() => CountFrequencyA(toProcess, letterFreq)),
Task.Run(() => CountFrequencyB(toProcess, letterFreq))
};
Task.WaitAll(tasks);
}
static void ProduceLetters(ConcurrentQueue<char> toProcess)
{
var rnd = new Random(DateTime.UtcNow.Millisecond);
const int numLetters = (int)'f' - (int)'a';
while(true)
{
int r = rnd.Next(0, numLetters);
var c = (char)((int)'a' + r);
toProcess.Enqueue(c);
}
}
/// <summary>
/// Count frequency using AddOrUpdate and GetOrAdd methods.
/// </summary>
static void CountFrequencyA(ConcurrentQueue<char> toProcess, ConcurrentDictionary<char, int> freq)
{
while (true)
{
char c;
if (!toProcess.TryDequeue(out c))
{
continue;
}
int updatedValue = freq.AddOrUpdate(c, 1, (key, oldValue) => oldValue + 1);
// Other thread could have updated count here
int currentValue = freq.GetOrAdd(c, 0);
if (updatedValue != currentValue)
{
DisplayDataRace(c, updatedValue, currentValue);
}
}
}
/// <summary>
/// Count frequency using Try#### methods
/// </summary>
static void CountFrequencyB(ConcurrentQueue<char> toProcess, ConcurrentDictionary<char, int> freq)
{
while (true)
{
char c;
if (!toProcess.TryDequeue(out c))
{
continue;
}
// Keep trying to update
bool hasUpdated = false;
while (!hasUpdated)
{
int oldValue;
if (!freq.TryGetValue(c, out oldValue))
{
if (!freq.TryAdd(c, 0))
{
continue; // try to add to dictionary again.
}
}
int updatedValue = oldValue + 1;
if (!freq.TryUpdate(c, updatedValue, oldValue))
{
continue; // Try again
}
hasUpdated = true;
// Other thread could have updated count here
int currentValue;
if (!freq.TryGetValue(c, out currentValue))
{
currentValue = 0;
}
if (updatedValue != currentValue)
{
DisplayDataRace(c, updatedValue, currentValue);
}
}
}
}
static object _displayLock = new Object();
private static void DisplayDataRace(char c, int updatedValue, int currentValue)
{
lock (_displayLock)
{
Console.WriteLine("[{0}] Updated Value: {1} Current Value: {2}", c.ToString(), updatedValue, currentValue);
}
}
}
}