Я не понимаю, какие "поколения" находятся в контексте Сборки "мусора". Кто-то может объяснить простыми словами?
Здесь есть две возможности для проблем:
AddElement
и ClearList
вызываются одновременно, у вас есть условие гонки: либо элемент окажется в новом списке, либо в старом (забытом). Список < T >
небезопасен для многопоточных мутаций, поэтому, если два разных потока одновременно вызывают AddElement
, результаты не гарантируются Учитывая, что вы получаете доступ к общему ресурсу, я лично держу блокировку при доступе к нему. Вам все еще нужно рассмотреть возможность очистки списка непосредственно перед/после добавления предмета.
EDIT: Мой комментарий о том, что это нормально, если вы добавляете только из одного потока, уже был несколько сомнительным, по двум причинам:
список < T >
, который еще не был полностью построен. Я не уверен, и модель памяти .NET 2.0 (в отличие от модели в спецификации ECMA) может быть достаточно сильной, чтобы избежать этого, но это сложно сказать. list
немедленно и все равно добавит в старый список. Действительно, без какой-либо синхронизации, он может видеть старое значение навсегда Когда вы добавляете «итерацию в GUI» в микс он становится действительно сложным - потому что вы не можете изменить список во время итерации. Наиболее простым решением является, вероятно, предоставление метода, который возвращает копию списка, и пользовательский интерфейс может безопасно выполнять итерацию над этим:
class A
{
private List<SomeClass> list;
private readonly object listLock = new object();
private void ClearList()
{
lock (listLock)
{
list = new List<SomeClass>();
}
}
private void AddElement()
{
lock (listLock)
{
list.Add(new SomeClass(...));
}
}
private List<SomeClass> CopyList()
{
lock (listLock)
{
return new List<SomeClass>(list);
}
}
}
-121--4631686- Да - возможно,. На самом деле, если их действительно называют одновременно, это весьма вероятно.
Кроме того, существует вероятность возникновения проблем при одновременном выполнении двух отдельных вызовов addElement.
Для такого рода многопоточности действительно нужна какая-то взаимоисключающая блокировка вокруг самого списка, поэтому одновременно можно вызвать только одну операцию в базовом списке.
Грубая стратегия блокировки вокруг этого поможет. Что-то вроде:
class A
{
static object myLock = new object()
List<SomeClass> list;
private void clearList()
{
lock(myLock)
{
list = new List<SomeClass>();
}
}
private void addElement()
{
lock(myLock)
{
list.Add(new SomeClass(...));
}
}
}
-121--4631687- Из Общие сведения о сборе мусора в .NET
Поколения
Сборщик мусора поколений собирает недолговечные объекты больше часто, чем более длинные живые. Недолговечные объекты хранятся в первое поколение, поколение 0. более долговечные объекты вставляются в высших поколений, 1 или 2. сборщик мусора работает больше часто в низших поколениях чем в высших.
При первом создании объекта он в генерацию 0. Когда поколение 0 заполнено, мусор вызывается коллектор. Объекты, которые пережить сбор мусора в первое поколение продвигается на следующее высшее поколение, поколение 1.Объекты, которые выживают мусор коллекция в поколении 1 повышен до следующего и самого высокого генерация, генерация 2. Это алгоритм работает эффективно для мусорный сбор объектов, как он быстро. Обратите внимание, что поколение 2 самое высокое поколение, которое поддерживается сборщиком мусора.
При выделении памяти управляемая куча быстрая, сам GC может занять некоторое время. Принимая это во внимание выполнено несколько оптимизаций для повышения производительности. ГХ поддерживает концепцию поколений, исходя из предположения, что дольше объект находился в куче, чем дольше он, вероятно, останется там. При назначении объекта на куча, которой она принадлежит в поколении 0. Каждый мусорный сбор, который объект выживает увеличивает генерация на 1 (в настоящее время самый высокий поддерживается генерация 2). Очевидно, это быстрее для поиска, и мусор собирают подмножество всех объекты в куче, так что GC имеет вариант сбора только генерации 0, 1 или 2 объекта (или что угодно комбинация, которую он выбирает, пока не получит достаточный объем памяти). Даже пока сбор только более молодых объектов GC может также определить, имеют ли старые объекты ссылки на новые объекты для обеспечения что он не игнорирует непреднамеренно используемые объекты.
В «Pro C # 2008» есть хорошее описание: