Потокобезопасность инициализации Comparer<T>.Default
От: WolfHound  
Дата: 28.01.09 14:36
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>О чем ты? Это всего лишь создание дефолтного компаратора. Ну, создадут его (в вырожденном случае) 3 раза параллельно и что? Все равно они одинаковые.

VD>И на скорость это тоже влиять не будет. Так как создаются компораторы по одному для типа.
Меня не это беспокоит.

WH>>ИМХО межу этими строками нужен барьер памати

WH>>
WH>>            defaultComparer = Comparer<T>.CreateComparer();
WH>>            //вот тут
WH>>            Comparer<T>.defaultComparer = defaultComparer;
WH>>

WH>>[/паранойя]
VD>Зачем?
За тем что второй поток может увидеть указатель на компатор до того как тело компатора приедит к нему.
Для того чтобы гарантировать что второй поток полностью увидит тело компатора нужен барьер памяти.

VD>Понятно. Но красно-черное дерево автоматически барансируется и у него относительно дешёвое обновление.

Дело в том что красно-черное дерево это по сути извращенная форма 2-3 дерева.
В свою очередь 2-3 дерево это частный случай B-дерева.
А с балансировкой у B-деревьев все в порядке.
Плюс в том что 2-3 деревья плодят меньше объектов и требуют меньше вычислений при вставке.
Короче вскрытие покажет кто быстрее.

VD>И вообще это уже выливается в новую структуру данных. Трудозатрат будет намного больше чем просто поправить имеющуюся реализацию.

Ну хочется мне 2-3 дерево написать. Тебе жалко что-ли?
Вставку уже написал. Сейчас думаю как удаление сделать красиво и эффективно.

VD>Это ты о Sum(), Subtract(), Intersect() и Xor() говоришь?

VD>Там второй Set рассматривается как просто список. Так что проблем быть не должно.
При наивной реализации.
Но если действовать не в лоб, а используя свойства контейнера то можно и побыстрее... но будут проблемы с разными компаторами.


02.02.09 01:22: Ветка выделена из темы Nemerle.Collections.Set[int*char] и IComparable
Автор: Didro
Дата: 25.01.09
— VladD2
02.02.09 01:22: Перенесено модератором из 'Nemerle' — VladD2
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Потокобезопасность инициализации Comparer<T>.Default
От: Иванков Дмитрий Россия  
Дата: 28.01.09 20:17
Оценка:
Здравствуйте, WolfHound, Вы писали:
WH>Вставку уже написал. Сейчас думаю как удаление сделать красиво и эффективно.
Когда-то развлекался:
module MyList { //вспомогательно
 public Replace['a] (L : list['a], x : 'a, y : list['a]) : list['a];
 public indexOf['a] (L : list['a], x : 'a) : int;
}
[Record]
public class Tree {
 [Record]
 public class Node {
  public sons : list[Node];
  public isLeaf () : bool { List.IsEmpty (sons) }
  public sonsCount () : int { List.Length (sons) }
  public getBrother (s : Node) : Node * bool {
   match (MyList.indexOf (sons, s)) {
     | 0 => (List.Nth (sons, 1), true)
     | i => (List.Nth (sons, i - 1), false)
   }
  }
 };
 root : Node;
 public Replace (path : list[Node], lst : list[Node]) : Tree
 requires List.Length (lst) <= 2
//requires lst.ForAll(x => x.height () == path.Head.height ()) //примерно так
 {
   | ([_], [l]) => Tree (l)
   | ([_], [l1, l2]) => Tree (Node ([l1, l2]))
   | (q :: w :: rst, _) =>
     def l = MyList.Replace (w.sons, q, lst);
     match(List.Length (l)) {
       | 2 | 3 => Replace (w :: rst, [Node (l)])
       | 1 when List.IsEmpty (rst) => Tree (l.Head)
       | 1 =>
         def e = rst.Head;
         def ls = MyList.Replace (e.sons, w, []);
         def (b, lft) = e.getBrother (w);
         if (lft)
           Replace (b.sons.Head :: b :: rst, [l.Head, b.sons.Head])
         else
           Replace (b.sons.Last :: b :: rst, [b.sons.Last, l.Head])
       | 4 =>
         def l1 = l.FirstN (2);
         def l2 = l.ChopFirstN (2);
         Replace (w :: rst, [Node (l1), Node (l2)])
     }
 }
 public height () : int; // в лоб
 public static merge (L : Tree, R : Tree) : Tree {
  def Lh = L.height ();
  def Rh = R.height ();
  if (Lh == Rh)
   Tree (Node ([L.root, R.root]))
  else {
   if (Lh < Rh) {
    def g(n, x) {
     | (_, 0) => [n]
     | _ => n :: g (n.sons.Head, x - 1)
    }
    def p = g(R.root, Rh - Lh);
    R.Replace (p, [L.root, p.Head])
   } else {
    def g(n, x) {
     | (_, 0) => [n]
     | _ => n :: g (n.sons.Last, x - 1)
    }
    def p = g(L.root, Lh - Rh);
    L.Replace (p, [p.Head, R.root])
   }
  }
 }
};

Replace позволяет делать вставку, удаление, замену произвольного узла. На его базе + Find легко построить Set.
Merge сливает два дерева, до Split не добрался
Re: Потокобезопасность инициализации Comparer<T>.Default
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.01.09 04:21
Оценка: +1
Здравствуйте, WolfHound, Вы писали:

WH>За тем что второй поток может увидеть указатель на компатор до того как тело компатора приедит к нему.

WH>Для того чтобы гарантировать что второй поток полностью увидит тело компатора нужен барьер памяти.

Я не вижу тут проблем:
public static Comparer<T> Default
{
    get
    {
        Comparer<T> defaultComparer = Comparer<T>.defaultComparer;
        if (defaultComparer == null)
        {
            defaultComparer = Comparer<T>.CreateComparer();
            Comparer<T>.defaultComparer = defaultComparer;
        }
        return defaultComparer;
    }
}

Comparer<T>.defaultComparer присваивается в самом конце когда компаратор уже сформирован.
Единственное, что может быть — параллельно сформируется два или более компаратора и только один из них останется в поле. Но это не проблема. По функциональности они будут идентичны. Так что если кто-то получит не тот компаратор, проблем это не создаст.

VD>>Понятно. Но красно-черное дерево автоматически барансируется и у него относительно дешёвое обновление.

WH>Дело в том что красно-черное дерево это по сути извращенная форма 2-3 дерева.
WH>В свою очередь 2-3 дерево это частный случай B-дерева.
WH>А с балансировкой у B-деревьев все в порядке.

Я поглядел алгоритм. С балансировкой там и правда все ОК. Память тоже видимо должна использоваться более экономично. Вопрос только в затратах на вставку/удаление.

WH>Короче вскрытие покажет кто быстрее.


Именно.

WH>Ну хочется мне 2-3 дерево написать. Тебе жалко что-ли?


Нет. Пиши на здоровье. Только интерфейс воспроизведи, чтобы можно было махнуть на ходу.

WH>Вставку уже написал. Сейчас думаю как удаление сделать красиво и эффективно.


Там что вставка, что удаление должны выглядеть очень похоже. Сначала нужно заменить ветки от корня до вставляемой, а пром баланс поправить. Если это сделать за один проход, то будет эффективнее.

VD>>Это ты о Sum(), Subtract(), Intersect() и Xor() говоришь?

VD>>Там второй Set рассматривается как просто список. Так что проблем быть не должно.
WH>При наивной реализации.
WH>Но если действовать не в лоб, а используя свойства контейнера то можно и побыстрее... но будут проблемы с разными компаторами.

Как можно что-то быстрее сделать? Ну, для Intersect или Xor еще что-то можно придумать. Но Sum и Subtract — это по любому вставка или удаление ВСЕХ элементов одного списка из другого. Так и в оригинальном списке сделано.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Потокобезопасность инициализации Comparer<T>.Default
От: WolfHound  
Дата: 29.01.09 15:26
Оценка: 12 (1)
Здравствуйте, VladD2, Вы писали:

VD>Я не вижу тут проблем:

хъ
VD>Comparer<T>.defaultComparer присваивается в самом конце когда компаратор уже сформирован.
Следи за рукам: Есть 2 разных куска памяти.
Первый содержит сам компатор. Второй содержит ссылку на компатор.
Если второй поток сначала получит второй кусок памяти и не получит первый (на некоторых архитектурах такое возможно) получим чтение не пойми чего и как следствие не пойми какие последствия. Ну ты на С++ писал...
Если вставить барьер памяти то второй поток гарантировано увидит первый кусок памяти раньше чем второй.

VD>Я поглядел алгоритм. С балансировкой там и правда все ОК. Память тоже видимо должна использоваться более экономично. Вопрос только в затратах на вставку/удаление.

Если вправить мозги компилятору будет быстрее.
Пока медленней.

VD>Там что вставка, что удаление должны выглядеть очень похоже. Сначала нужно заменить ветки от корня до вставляемой, а пром баланс поправить. Если это сделать за один проход, то будет эффективнее.

Оно сразу сбалансированным строится.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: Потокобезопасность инициализации Comparer<T>.Default
От: Константин Л. Турция  
Дата: 29.01.09 15:29
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, VladD2, Вы писали:


VD>>Я не вижу тут проблем:

WH>хъ
VD>>Comparer<T>.defaultComparer присваивается в самом конце когда компаратор уже сформирован.
WH>Следи за рукам: Есть 2 разных куска памяти.
WH>Первый содержит сам компатор. Второй содержит ссылку на компатор.
WH>Если второй поток сначала получит второй кусок памяти и не получит первый (на некоторых архитектурах такое возможно) получим чтение не пойми чего и как следствие не пойми какие последствия. Ну ты на С++ писал...
WH>Если вставить барьер памяти то второй поток гарантировано увидит первый кусок памяти раньше чем второй.

Такого быть не может

[]
Re[3]: Потокобезопасность инициализации Comparer<T>.Default
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.01.09 17:33
Оценка:
Здравствуйте, WolfHound, Вы писали:

VD>>Comparer<T>.defaultComparer присваивается в самом конце когда компаратор уже сформирован.

WH>Следи за рукам: Есть 2 разных куска памяти.
WH>Первый содержит сам компатор. Второй содержит ссылку на компатор.
WH>Если второй поток сначала получит второй кусок памяти и не получит первый (на некоторых архитектурах такое возможно) получим чтение не пойми чего и как следствие не пойми какие последствия. Ну ты на С++ писал...
WH>Если вставить барьер памяти то второй поток гарантировано увидит первый кусок памяти раньше чем второй.

Какой еще кусок памяти? Копирование ссылочных полей в донтете операция атомарная. Что за проблемы ты находишь?

VD>>Я поглядел алгоритм. С балансировкой там и правда все ОК. Память тоже видимо должна использоваться более экономично. Вопрос только в затратах на вставку/удаление.

WH>Если вправить мозги компилятору будет быстрее.
WH>Пока медленней.

Что-то мне мне кажется, что дело не в компиляторе. КЧД компилятор не мешал. Вот компаратор действительном может затормозить все.

Ты бы код показал. Может общими усилиями получилось бы найти что в нем подтюнить.

VD>>Там что вставка, что удаление должны выглядеть очень похоже. Сначала нужно заменить ветки от корня до вставляемой, а пром баланс поправить. Если это сделать за один проход, то будет эффективнее.

WH>Оно сразу сбалансированным строится.

Замечательно. Тогда не ясно почему медленно получается.

А медленно это по сравнению с чем? Ты пробовал подменять им исходный Set и замерять скорость самосборки компилятора.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Потокобезопасность инициализации Comparer<T>.Default
От: WolfHound  
Дата: 29.01.09 18:33
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Какой еще кусок памяти? Копирование ссылочных полей в донтете операция атомарная.

Расшаренная между потоками ссылка это один кусок памяти.
Объект компатор это другой косок памяти.

VD>Что за проблемы ты находишь?

Проблемы с шареной между потоками памятью. Там на всамом деле все весело. Особенно учитывая разные модели памяти на разных процессорах.
Я знаю что у .NET'а есть своя модель памяти но где гарантия что ее на каждом конкретном процессоре корректно реализуют?
Да я и не уверен что она дает в данном конкретном случае нужные гарантии.
В любом случае race condition на лицо и как следствие нужно соломку подстелить.
nikov что скажешь?

VD>Что-то мне мне кажется, что дело не в компиляторе. КЧД компилятор не мешал. Вот компаратор действительном может затормозить все.

В нем. В чем же еще?
Переписал вставку императивненько стало на 15% быстрее родного Set'а, а было в 2 раза медленней.

VD>Ты бы код показал. Может общими усилиями получилось бы найти что в нем подтюнить.

Да я и сам могу.
В данном случае выяснил что возвращать из функции кортежи это медленно.
Пришлось возвращать через изменяемые переменные. Не красиво за-то быстро.

VD>Замечательно. Тогда не ясно почему медленно получается.

Глупый компилятор.
Причем не только немерле но и JIT.

VD>А медленно это по сравнению с чем? Ты пробовал подменять им исходный Set и замерять скорость самосборки компилятора.

Ну так я с ним и гоняюсь.
Интерфес то в той части что я сделал одинаковый.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: Потокобезопасность инициализации Comparer<T>.Default
От: nikov США http://www.linkedin.com/in/nikov
Дата: 29.01.09 20:42
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Проблемы с шареной между потоками памятью. Там на всамом деле все весело. Особенно учитывая разные модели памяти на разных процессорах.

WH>Я знаю что у .NET'а есть своя модель памяти но где гарантия что ее на каждом конкретном процессоре корректно реализуют?
WH>Да я и не уверен что она дает в данном конкретном случае нужные гарантии.
WH>В любом случае race condition на лицо и как следствие нужно соломку подстелить.
WH>nikov что скажешь?

Я думаю, ты прав. Ecma-335:

12.6.8 Other memory model issues
All memory allocated for static variables (other than those assigned RVAs within a PE file, see Partition II) and
objects shall be zeroed before they are made visible to any user code.
A conforming implementation of the CLI shall ensure that, even in a multi-threaded environment and without
proper user synchronization, objects are allocated in a manner that prevents unauthorized memory access and
prevents invalid operations from occurring. In particular, on multiprocessor memory systems where explicit
synchronization is required to ensure that all relevant data structures are visible (for example, vtable pointers)
the Execution Engine shall be responsible for either enforcing this synchronization automatically or for
converting errors due to lack of synchronization into non-fatal, non-corrupting, user-visible exceptions.
It is explicitly not a requirement that a conforming implementation of the CLI guarantee that all state updates
performed within a constructor be uniformly visible before the constructor completes. CIL generators can
ensure this requirement themselves by inserting appropriate calls to the memory barrier or volatile write
instructions.


То есть, самое худшее, что может случиться по стандарту — неожиданное исключение, потому что поток "увидит" по ссылке память, заполненную нулями (в т.ч. служебные поля объекта). Но насколько мне известно, реализация MS устроена так, что write выполняется как volatile write.
Re[5]: Потокобезопасность инициализации Comparer<T>.Default
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.01.09 23:46
Оценка:
Здравствуйте, WolfHound, Вы писали:

Слушай кончай антазировать. Нет там никаких проблем. Копирование ссылки — атомарная операция. Объект сначала формируется, а потом ссылка на него помещается в переменную. Неинициализированного объекта никто не увидит. Самое страшное, что случится — это могут создаться несколько копий компораторов, но так как они все равно будут идентичны, то по фигу кто какую копию будет использовать. Итого проблем тут быть не может.

Если бы проблемы были, то форумы давно были бы завалены вопросами "почему у меня глючит ... при вызове из двух потоков".

В общем, класс писал не ты. Оставь это тем кто его писал. Можешь им даже свои мыли изложить.
Но нельзя браться за сто дел сразу. Ни одного не сделаешь ведь. Так что забей на это.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Потокобезопасность инициализации Comparer<T>.Default
От: WolfHound  
Дата: 30.01.09 04:29
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Если бы проблемы были, то форумы давно были бы завалены вопросами "почему у меня глючит ... при вызове из двух потоков".

Это гейзенбаг. Его не так то просто увидить.
Но он есть и его надо фиксить.

VD>В общем, класс писал не ты. Оставь это тем кто его писал. Можешь им даже свои мыли изложить.

Тут есть nikov. Он может им передать.
Тем более что он со мной согласен.
Кстати хорошая иллюстрация на тему что многопоточность на шареной памяти мало кто понимает.

VD>Но нельзя браться за сто дел сразу. Ни одного не сделаешь ведь. Так что забей на это.

А можно я сам разберусь сколько мне дел одновременно делать?
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: Потокобезопасность инициализации Comparer<T>.Default
От: nikov США http://www.linkedin.com/in/nikov
Дата: 30.01.09 10:01
Оценка: +2
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, WolfHound, Вы писали:

VD>Слушай кончай антазировать. Нет там никаких проблем. Копирование ссылки — атомарная операция. Объект сначала формируется, а потом ссылка на него помещается в переменную.
По спецификации — вовсе не обязательно. В многопроцессорной среде понятия сначала/потом являются отностительными. Если реализация MS сейчас ведет себя более безопасно, то это не значит, что она будет вести себя так завтра на 32-процессорной машине, или что другие моно/шмоно будут себя так вести. Это предупреждение в спецификацию неспроста вставили.
Однако, благодаря предварительному обнулению кучи, самое худшее, что может случиться — это исключение. Никакого повреждения памяти или получения постороннего объекта.
Re[7]: Потокобезопасность инициализации Comparer<T>.Default
От: Константин Л. Турция  
Дата: 30.01.09 10:21
Оценка:
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, VladD2, Вы писали:


VD>>Здравствуйте, WolfHound, Вы писали:

VD>>Слушай кончай антазировать. Нет там никаких проблем. Копирование ссылки — атомарная операция. Объект сначала формируется, а потом ссылка на него помещается в переменную.
N>По спецификации — вовсе не обязательно. В многопроцессорной среде понятия сначала/потом являются отностительными. Если реализация MS сейчас ведет себя более безопасно, то это не значит, что она будет вести себя так завтра на 32-процессорной машине, или что другие моно/шмоно будут себя так вести. Это предупреждение в спецификацию неспроста вставили.
N>Однако, благодаря предварительному обнулению кучи, самое худшее, что может случиться — это исключение. Никакого повреждения памяти или получения постороннего объекта.

Так. Стоп. Что значит сначала/потом. Давайте разберемся как будет создаваться объект.

1. Выделяется память
2. На ней зовется ctor
3. Ссылка на память присваивается переменной

Вы патаетесь сказать, что порядок может быть 1,3,2? Какой в этом смысл?
Re[8]: Потокобезопасность инициализации Comparer<T>.Default
От: nikov США http://www.linkedin.com/in/nikov
Дата: 30.01.09 10:28
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Так. Стоп. Что значит сначала/потом. Давайте разберемся как будет создаваться объект.


КЛ>1. Выделяется память

КЛ>2. На ней зовется ctor
КЛ>3. Ссылка на память присваивается переменной

КЛ>Вы патаетесь сказать, что порядок может быть 1,3,2? Какой в этом смысл?


Порядок, в котором другой поток, выполняющийся на другом проце с другими кэшами, увидит эти изменения может быть другим. Смысл — ускорить работу за счет снижения гарантий. Тот, кому нужны гарантии — вставляет ручную синхронизацию и барьеры (например, их могут вставлять компиляторы из языков высокго уровня в IL) и профилирует замедление.
Re[9]: Потокобезопасность инициализации Comparer<T>.Default
От: Константин Л. Турция  
Дата: 30.01.09 10:35
Оценка:
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, Константин Л., Вы писали:


КЛ>>Так. Стоп. Что значит сначала/потом. Давайте разберемся как будет создаваться объект.


КЛ>>1. Выделяется память

КЛ>>2. На ней зовется ctor
КЛ>>3. Ссылка на память присваивается переменной

КЛ>>Вы патаетесь сказать, что порядок может быть 1,3,2? Какой в этом смысл?


N>Порядок, в котором другой поток, выполняющийся на другом проце с другими кэшами, увидит эти изменения может быть другим. Смысл — ускорить работу за счет снижения гарантий. Тот, кому нужны гарантии — вставляет ручную синхронизацию и барьеры (например, их могут вставлять компиляторы из языков высокго уровня в IL) и профилирует замедление.


А до п. 3 других потоков эти изменения не интересуют. Точнее так: они полюбому должны увидеть что память выделилась, иначе ничего работать не будет, им пофиг, вызвался ctor или нет, им пофиг, что они увидять не сразу, что статическая переменная уже ссылается на объект
Re[8]: Потокобезопасность инициализации Comparer<T>.Default
От: WolfHound  
Дата: 30.01.09 10:38
Оценка: +1
Здравствуйте, Константин Л., Вы писали:

КЛ>Вы патаетесь сказать, что порядок может быть 1,3,2? Какой в этом смысл?

Нет.
Операции идут последовательно.
НО! Каждая из них модифицирует разные области памяти.
И результат модификации этих областей в другом потоке может быть виден в другом порядке.
Чтобы этого небыло нужно дергать барьер памяти.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[9]: Потокобезопасность инициализации Comparer<T>.Default
От: Константин Л. Турция  
Дата: 30.01.09 10:41
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, Константин Л., Вы писали:


КЛ>>Вы патаетесь сказать, что порядок может быть 1,3,2? Какой в этом смысл?

WH>Нет.
WH>Операции идут последовательно.
WH>НО! Каждая из них модифицирует разные области памяти.
WH>И результат модификации этих областей в другом потоке может быть виден в другом порядке.
WH>Чтобы этого небыло нужно дергать барьер памяти.

тогда никаких проблем быть не может. главное что выделение памяти потоки видят одновременно.
Re[10]: Потокобезопасность инициализации Comparer<T>.Default
От: nikov США http://www.linkedin.com/in/nikov
Дата: 30.01.09 10:45
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>А до п. 3 других потоков эти изменения не интересуют. Точнее так: они полюбому должны увидеть что память выделилась, иначе ничего работать не будет, им пофиг, вызвался ctor или нет, им пофиг, что они увидять не сразу, что статическая переменная уже ссылается на объект


Я не совсем понимаю, что значит "увидеть что память выделилась". Может быть так, что статическая переменная уже ссылается на объект A, но память в куче, где этот объект должен лежать, с точки зрения какого-то потока еще заполнена нулями (хотя на самом деле конструктор уже отработал). И этот поток может словить исключение при вызове метода объекта A. Но если этот поток попробует создать какой-то другой объект, то он будет корректно размещен в куче после объекта А, потому что правильная работа кучи гарантируется без ручных блокировок (это и есть "увидеть что память выделилась"?).
Re[10]: Потокобезопасность инициализации Comparer<T>.Default
От: WolfHound  
Дата: 30.01.09 10:46
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>тогда никаких проблем быть не может. главное что выделение памяти потоки видят одновременно.

Ну если работа с объектом находящемся в произвольном состоянии включая служебные поля не проблема тогда что же для тебя проблема?
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[11]: Потокобезопасность инициализации Comparer<T>.Default
От: Константин Л. Турция  
Дата: 30.01.09 10:49
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, Константин Л., Вы писали:


КЛ>>тогда никаких проблем быть не может. главное что выделение памяти потоки видят одновременно.

WH>Ну если работа с объектом находящемся в произвольном состоянии включая служебные поля не проблема тогда что же для тебя проблема?

Где он находится в произвольном состоянии? Еще раз.

1. выделяем память (тут _все_ потоки должны это увидеть)
2. инициализируем объект (тут пофиг, ибо живых ссылок пока на эту память в проге нет, другим потокам на эту память о объект пофиг)
3. инициализируем статическую переменную ссылкой на объект

м?
Re[11]: Потокобезопасность инициализации Comparer<T>.Default
От: Константин Л. Турция  
Дата: 30.01.09 10:53
Оценка:
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, Константин Л., Вы писали:


КЛ>>А до п. 3 других потоков эти изменения не интересуют. Точнее так: они полюбому должны увидеть что память выделилась, иначе ничего работать не будет, им пофиг, вызвался ctor или нет, им пофиг, что они увидять не сразу, что статическая переменная уже ссылается на объект


N>Я не совсем понимаю, что значит "увидеть что память выделилась".


Это значит, что все потоки имеют правильную информацию о значении того преславутого курсора в мэнеджед хипе.

N>Может быть так, что статическая переменная уже ссылается на объект A, но память в куче, где этот объект должен лежать, с точки зрения какого-то потока еще заполнена нулями (хотя на самом деле конструктор уже отработал). И этот поток может словить исключение при вызове метода объекта A. Но если этот поток попробует создать какой-то другой объект, то он будет корректно размещен в куче после объекта А, потому что правильная работа кучи гарантируется без ручных блокировок (это и есть "увидеть что память выделилась"?).


Такого быть не может.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.