Re[3]: Memory reordering
От: Sharov Россия  
Дата: 09.04.15 09:54
Оценка: 4 (1)
Здравствуйте, mrTwister, Вы писали:

S>>race condition, b уже не null, но еще не 42...


T>А как к этому могут привести переупорядочивание "Read 1" и "Read 2"?


Прощу прощения, перепутал.

Тут эта статья уже разбиралась, может интересно будет -- http://rsdn.ru/forum/dotnet/4989809.flat.1
Автор: SergeyT.
Дата: 07.12.12
Кодом людям нужно помогать!
Re: Memory reordering
От: Mr.Delphist  
Дата: 16.04.15 13:55
Оценка: +1
Здравствуйте, mrTwister, Вы писали:

T>Читал тут статью в которой есть пример:

T>
T>class BoxedInt
T>{
T>  public int Value { get; set; }
T>}
T>class LazyInit
T>{
T>  volatile BoxedInt _box;
T>  public int LazyGet()
T>  {
T>    var b = _box;  // Read 1
T>    if (b == null)
T>    {
T>      lock(this)
T>      {
T>        b = new BoxedInt();
T>        b.Value = 42; // Write 1
T>        _box = b;     // Write 2
T>      }
T>    }
T>    return b.Value; // Read 2
T>  }
T>}
T>


Ну и ход в сторону: использование lock(this) не рекомендуется, лучше завести отдельный object для этих целей.
Memory reordering
От: mrTwister Россия  
Дата: 09.04.15 08:05
Оценка:
Читал тут статью в которой есть пример:
class BoxedInt
{
  public int Value { get; set; }
}
class LazyInit
{
  volatile BoxedInt _box;
  public int LazyGet()
  {
    var b = _box;  // Read 1
    if (b == null)
    {
      lock(this)
      {
        b = new BoxedInt();
        b.Value = 42; // Write 1
        _box = b;     // Write 2
      }
    }
    return b.Value; // Read 2
  }
}


Утверждается следующее:

In this example, LazyGet is always guaranteed to return “42.” However, if the _box field were not volatile, LazyGet would be allowed to return “0” for two reasons: the reads could get reordered, or the writes could get reordered.



C "writes" все понятно, но как в данном случае могут быть переупорядочены (reordered) "Read 1" и "Read 2" так, чтобы вернулось 0, при том, что writes не переупорядочены?
лэт ми спик фром май харт
Re: Memory reordering
От: Sharov Россия  
Дата: 09.04.15 09:06
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Утверждается следующее:

T>

In this example, LazyGet is always guaranteed to return “42.” However, if the _box field were not volatile, LazyGet would be allowed to return “0” for two reasons: the reads could get reordered, or the writes could get reordered.



race condition, b уже не null, но еще не 42...
Кодом людям нужно помогать!
Re[2]: Memory reordering
От: mrTwister Россия  
Дата: 09.04.15 09:13
Оценка:
Здравствуйте, Sharov, Вы писали:

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


T>>Утверждается следующее:

T>>

In this example, LazyGet is always guaranteed to return “42.” However, if the _box field were not volatile, LazyGet would be allowed to return “0” for two reasons: the reads could get reordered, or the writes could get reordered.



S>race condition, b уже не null, но еще не 42...


А как к этому могут привести переупорядочивание "Read 1" и "Read 2"?
лэт ми спик фром май харт
Re: Memory reordering
От: drol  
Дата: 10.04.15 20:12
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>C "writes" все понятно, но как в данном случае могут быть переупорядочены (reordered) "Read 1" и "Read 2" так,


Здесь автор статьи слегка ерунду написал.

Read 1 и Read 2 не могут быть переупорядочены, бо являются зависимыми. Чтобы выполнить Read 2, нужно сначала узнать адрес, который даёт Read 1.

Однако это вовсе не означает, что всё хорошо.

В пределах пути исполнения кода в потоке все команды не-volatile чтения по одному конкретному адресу могут быть элиминированы путём замены на какое-нибудь локальное кэширование — в регистре\на стеке\в потрохах контроллера памяти — результата самого первого такого чтения. Сия оптимизация корректна на всех отрезках пути исполнения кода между командами записи и\или volatile чтения по данному конкретному адресу.

И в исходном примере, если поток словил момент передачи недосконструированного\недоинициализированного объекта, то в общем случае возможна ситуация, когда все дальнейшие вызовы LazyGet() в этом потоке будут приводить к возвращению 0, несмотря на то, что в памяти значение уже давно поменялось.

T>чтобы вернулось 0, при том, что writes не переупорядочены?


Если путь исполнения кода в потоке не проходит через внутренности if, то Write'ов вообще нет.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.