c# · level 3 · unit 7 · lesson 2
- meet it
- guess first
- your turn
- fix it
- nailed it
Tap a green word if you get lost.
meet it
A lets many threads count together.
A plain Dictionary is not : two threads adding at once can corrupt it. ConcurrentDictionary<TKey, TValue> is built for sharing, and each of its methods does its whole job in one safe step.
Counting from many threads hides a trap called : checking for a key, then adding it, leaves a gap between the two steps. AddOrUpdate(colour, 1, (key, old) => old + 1) closes the gap. It adds 1 for a new key or updates the old count, all in one step.
Its entries come out in no fixed order, so sort them before printing.
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
string[] lines = { "red blue red", "blue green", "red green green" };
var counts = new ConcurrentDictionary<string, int>();
var jobs = lines.Select(line => Task.Run(() =>
{
foreach (string colour in line.Split(' '))
{
counts.AddOrUpdate(colour, 1, (key, old) => old + 1);
}
}));
await Task.WhenAll(jobs);
foreach (var pair in counts.OrderBy(p => p.Key))
{
Console.WriteLine($"{pair.Key}: {pair.Value}");
} counts.OrderBy(p => p.Key) sorts the entries by key, so the report reads the same every run.
guess first
Add, or get what is there. What will this show?
Guess before you run it. Wrong guesses are how you learn, and nothing is marked.
using System;
using System.Collections.Concurrent;
var stock = new ConcurrentDictionary<string, int>();
int a = stock.GetOrAdd("tea", 3);
int b = stock.GetOrAdd("tea", 9);
stock.AddOrUpdate("tea", 1, (key, old) => old * 10);
Console.WriteLine($"{a} {b} {stock["tea"]}");
your turn
Your turn. Total the sales by shop.
On line 14, finish the update lambda: when a shop already has a total, add this sale's amount to the old one.
output
press run to see what happens
fix it
The basket counter crashes. Can you fix it?
output
press run to see what happens
- It crashes with
KeyNotFoundExceptionon line 12. What is incountsthe first time an item arrives? counts[item]++reads the old count first, and a new item has none. It is also a check-then-act race.- Change line 12 to
counts.AddOrUpdate(item, 1, (key, old) => old + 1);, then run.
nailed it
your threads can share a dictionary now. :D
ConcurrentDictionaryis built for many threads at once.AddOrUpdateadds or updates in one safe step.- Sort its entries before printing a report.
new words in your collection
- thread-safe
- ConcurrentDictionary
- check-then-act
This lesson isn’t saved. A free account remembers every lesson you finish.