ConcurrentDictionary<T> и неизменяемые коллекции
Используйте ConcurrentDictionary для потокобезопасных обновлений и изучите простые неизменяемые подходы: представления только для чтения и копирование при записи.
«ConcurrentDictionary<T> и неизменяемые коллекции» — бесплатный урок C# Academy на CoddyKit. Это урок 2 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 3 уроков всего.
Основы потокобезопасности и неизменяемости
Сегодня:
- ConcurrentDictionary<TKey,TValue>: безопасные обновления из нескольких потоков
- Представления только для чтения и настоящая неизменяемость
- Идея копирования при записи для простой защиты
Атомарные операции: GetOrAdd/AddOrUpdate
Используйте GetOrAdd и AddOrUpdate для атомарных операций, а TryGetValue — для безопасного чтения.
using System;
using System.Collections.Concurrent;
public class Program
{
public static void Main(string[] args)
{
ConcurrentDictionary<string, int> counts = new ConcurrentDictionary<string, int>();
// Add if missing
int a = counts.GetOrAdd("apple", 0); // 0
// Increment safely
int newVal = counts.AddOrUpdate("apple", 1, (key, oldValue) => oldValue + 1);
Console.WriteLine("apple was " + a + ", now " + newVal);
int value;
bool ok = counts.TryGetValue("apple", out value);
Console.WriteLine("Has apple? " + ok + " -> " + value);
}
}
Идея приращения без состояния гонки
AddOrUpdate устраняет классическую гонку при чтении-изменении-записи, выполняя обновление атомарно.
using System;
using System.Collections.Concurrent;
public class Program
{
static int Inc(int oldValue) { return oldValue + 1; }
public static void Main(string[] args)
{
ConcurrentDictionary<string, int> clicks = new ConcurrentDictionary<string, int>();
// Simulate multiple updates
for (int i = 0; i < 5; i++)
{
clicks.AddOrUpdate("home", 1, delegate(string k, int v) { return Inc(v); });
}
Console.WriteLine("home clicks = " + clicks["home"]); // 5 (starting at 1 then +4)
}
}
Представление только для чтения (не неизменяемое)
AsReadOnly возвращает представление только для чтения, а не по-настоящему неизменяемую коллекцию: изменения источника отображаются в представлении.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main(string[] args)
{
List<string> items = new List<string>(new string[] { "A", "B" });
var ro = items.AsReadOnly(); // ReadOnlyCollection<string>
foreach (string s in ro) Console.WriteLine(s); // A, B
// ro.Add("C"); // not available: read-only view has no Add
// But changing the source list reflects in the view:
items.Add("C");
Console.WriteLine("After source change:");
foreach (string s in ro) Console.WriteLine(s); // A, B, C
}
}
Снимок с копированием при записи
Копирование при записи: при изменениях возвращайте новый список. Вызывающий код, сохранивший старый список, видит стабильный снимок.
using System;
using System.Collections.Generic;
public class Program
{
static List<int> AddWithoutTouchingOriginal(List<int> original, int item)
{
// create a copy and modify the copy
List<int> copy = new List<int>(original);
copy.Add(item);
return copy;
}
public static void Main(string[] args)
{
List<int> a = new List<int>(new int[] { 1, 2 });
List<int> b = AddWithoutTouchingOriginal(a, 3);
Console.WriteLine("Original:");
foreach (int x in a) Console.WriteLine(x); // 1,2
Console.WriteLine("Copy:");
foreach (int x in b) Console.WriteLine(x); // 1,2,3
}
}
Советы и компромиссы
Советы:
- Используйте ConcurrentDictionary для общих счётчиков и кэшей.
- AsReadOnly предотвращает случайное изменение данных потребителями.
- Чтобы получить стабильное представление, скопируйте список перед изменением.
- Настоящие неизменяемые коллекции находятся в System.Collections.Immutable (пакет); здесь они не используются, чтобы код оставался автономным.
Выбор потокобезопасного словаря
Повторение
Повторение: используйте ConcurrentDictionary для параллельных обновлений. Предоставляйте вызывающему коду представления только для чтения и применяйте копирование при записи, когда нужны стабильные снимки.
Часто задаваемые вопросы
Урок «ConcurrentDictionary<T> и неизменяемые коллекции» бесплатный?
Да — полный текст урока «ConcurrentDictionary<T> и неизменяемые коллекции» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 3 уроков всего.
Чему я научусь в уроке «ConcurrentDictionary<T> и неизменяемые коллекции»?
Используйте ConcurrentDictionary для потокобезопасных обновлений и изучите простые неизменяемые подходы: представления только для чтения и копирование при записи. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 3.
Сколько времени занимает урок «ConcurrentDictionary<T> и неизменяемые коллекции»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- HashSet , SortedSet , Queue , Stack
- ConcurrentDictionary и неизменяемые коллекции
- Равенство и хеширование (значения и ссылки)