Re[6]: wikipedia :: Double-checked locking
От: AndrewJD США  
Дата: 16.12.19 16:37
Оценка: +4
Здравствуйте, reversecode, Вы писали:

R>иногда вместо мютексов используют синхронизации на atomic-ах, называется это уже lockfree программирование


Атомики сами по себе не приводят к lockfree. Тот же классический спинлок на атомиках — попрежнему блокирующий алгоритм.
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re: wikipedia :: Double-checked locking
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 13.12.19 09:56
Оценка: 18 (1) +1 :)
Здравствуйте, kaa.python, Вы писали:

KP>В принципе всё логично и работать оно будет, но какой в данном случае смысл в std::memory_order_relaxed под мьютексом? Мьютекс же работает как барьер и в любом случае чтение пройдет как std::memory_order_acquire? Или я что-то путаю?


Acquire был раньше, когда мьютекс захватывался. А теперь можно, пока под мьютексом, прочесть максимально дешёвым и быстрым образом и не получить за это по рыжей морде каким-нибудь обгоном. Поэтому — relaxed.
Иначе бы получалось, что мьютекс уже захвачен, и снова вдруг подымается машина сериализации операций — а нафига собственно?
The God is real, unless declared integer.
Re[3]: wikipedia :: Double-checked locking
От: Шахтер Интернет  
Дата: 13.12.19 08:27
Оценка: 9 (1) +1
Здравствуйте, kaa.python, Вы писали:

KP>Здравствуйте, Шахтер, Вы писали:


Ш>>Это оптимизация. memory_order_relaxed -- самый дешёвый вид чтения. На x86 это просто считывание переменной. Поскольку оно происходит под мьютексом, никаких дополнительных гарантий не нужно.


KP>Я немного о другом. Разве мьютекс не является одновременно барьером? Если он является таковым, то memory_order_relaxed в данном случае не вносит никакой оптимизации.


KP>Если же утверждение выше не верно, то хотелось бы понять каким образом memory_order_relaxed привносит здесь оптимизацию?


Я не понимаю, чего здесь не понятного? Для считывания атомика нужно вызвать load с флагом. Флаг определяет дополнительные телодвижения, которые компилятор сгенерирует для соблюдения соответствующих гарантий.
Самый дешёвый флаг memory_order_relaxed. Он даёт только одну гарантию -- атомарность операции.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: wikipedia :: Double-checked locking
От: Vamp Россия  
Дата: 13.12.19 13:28
Оценка: +1 -1
Здравствуйте, $$, Вы писали:

$>Здравствуйте, Шахтер, Вы писали:

Ш>>Я не понимаю, чего здесь не понятного? Для считывания атомика нужно вызвать load с флагом.


$>Почему бы обычный volatile не использовать? Ведь буков меньше и на до- C++11 компиляторах соберётся.
Не ожидал такого вопроса в 2019 году... Рекомендую обратиться к первоисточникам.
Да здравствует мыло душистое и веревка пушистая.
Re: wikipedia :: Double-checked locking
От: Vamp Россия  
Дата: 13.12.19 13:34
Оценка: +1 -1
Про релаксед вроде объяснили. А вот на икса нам вообще нужен СимплСинглтон нуждается в дополнительном сра обсуждении.
Да здравствует мыло душистое и веревка пушистая.
Re[3]: wikipedia :: Double-checked locking
От: PM  
Дата: 13.12.19 15:46
Оценка: 10 (1)
Здравствуйте, sergey2b, Вы писали:

S>а где нибудь можно про это почитать в систематизированном виде ?

S>те не в викпедии

Про потокобезопасное создание singleton? Подробный разбор был в https://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/

Про memory order у атомарных инструкций? На https://en.cppreference.com/w/cpp/atomic/memory_order неплохо написано.

Про многопоточность в С++ вообще? C++ Concurrency in Action by Anthony Williams
Re[3]: wikipedia :: Double-checked locking
От: Vamp Россия  
Дата: 13.12.19 15:56
Оценка: 10 (1)
Здравствуйте, sergey2b, Вы писали:

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


N>>Acquire был раньше, когда мьютекс захватывался. А теперь можно, пока под мьютексом, прочесть максимально дешёвым и быстрым образом и не получить за это по рыжей морде каким-нибудь обгоном. Поэтому — relaxed.

N>>Иначе бы получалось, что мьютекс уже захвачен, и снова вдруг подымается машина сериализации операций — а нафига собственно?

S>а где нибудь можно про это почитать в систематизированном виде ?

S>те не в викпедии

Вот тут неплохо: https://stackoverflow.com/questions/6319146/c11-introduced-a-standardized-memory-model-what-does-it-mean-and-how-is-it-g
Да здравствует мыло душистое и веревка пушистая.
Re: wikipedia :: Double-checked locking
От: Шахтер Интернет  
Дата: 13.12.19 05:58
Оценка: +1
Здравствуйте, kaa.python, Вы писали:

KP>По мотивам одного из срачей
Автор: aik
Дата: 13.12.19
, я наткнулся на несколько озадачевшею меня реализацию Double-checked locking:

KP>
KP>#include <atomic>
KP>#include <mutex>

KP>class Singleton {
KP> public:
KP>  Singleton* GetInstance();

KP> private:
KP>  Singleton() = default;

KP>  static std::atomic<Singleton*> s_instance;
KP>  static std::mutex s_mutex;
KP>};

KP>Singleton* Singleton::GetInstance() {
KP>  Singleton* p = s_instance.load(std::memory_order_acquire);
KP>  if (p == nullptr) {
KP>    std::lock_guard<std::mutex> lock(s_mutex);
KP>    p = s_instance.load(std::memory_order_relaxed);    // <- это
KP>    if (p == nullptr) {
KP>      p = new Singleton();
KP>      s_instance.store(p, std::memory_order_release);
KP>    }
KP>  }
KP>  return p;
KP>}
KP>


KP>В принципе всё логично и работать оно будет, но какой в данном случае смысл в std::memory_order_relaxed под мьютексом? Мьютекс же работает как барьер и в любом случае чтение пройдет как std::memory_order_acquire? Или я что-то путаю?


Это оптимизация. memory_order_relaxed -- самый дешёвый вид чтения. На x86 это просто считывание переменной. Поскольку оно происходит под мьютексом, никаких дополнительных гарантий не нужно.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: А смысл?
От: landerhigh Пират  
Дата: 13.12.19 08:47
Оценка: -1
Здравствуйте, kaa.python, Вы писали:

KP>По мотивам одного из срачей
Автор: aik
Дата: 13.12.19
, я наткнулся на несколько озадачевшею меня реализацию Double-checked locking:


По мотивам подобного срача рефакторинга окаменелых говен, хотелось бы задать публике вопрос — имеет ли подобный ментальный онанизм красивый паттерн вообще какой-то стратегический смысл?
Постановка вопроса подразумевает, что объект под синглтоном делает что-то полезное и используется из разных потоков. Но делающий что-то полезное объект в данном случае должен сам обеспечивать потокобезопасность своих методов. Что в большинстве случае означает, явный или неявный lock внутри делающих что-то полезное методов.

Короче, за что боремся?
www.blinnov.com
Re[4]: wikipedia :: Double-checked locking
От: $$ Австралия жж
Дата: 13.12.19 12:21
Оценка: :)
Здравствуйте, Шахтер, Вы писали:

Ш>Я не понимаю, чего здесь не понятного? Для считывания атомика нужно вызвать load с флагом.


Почему бы обычный volatile не использовать? Ведь буков меньше и на до- C++11 компиляторах соберётся.
Re[6]: wikipedia :: Double-checked locking
От: Videoman Россия https://hts.tv/
Дата: 13.12.19 15:24
Оценка: -1
Здравствуйте, Vamp, Вы писали:

V>$>Почему бы обычный volatile не использовать? Ведь буков меньше и на до- C++11 компиляторах соберётся.

V>Не ожидал такого вопроса в 2019 году... Рекомендую обратиться к первоисточникам.

Безотносительно того, что volatile тут не поможет, хотелось бы заметить, что по коду сразу не понятно в каком году он написан, но судя по тому что в нем все еще гуляют голые указатели, а не std::unique_ptr — явно раньше 11-го года
И вообще, в С++11 уже давно появился std::call_once, который без лишних вопросов, должен решить проблему создания одного объекта.
Отредактировано 13.12.2019 15:26 Videoman . Предыдущая версия . Еще …
Отредактировано 13.12.2019 15:25 Videoman . Предыдущая версия .
Re[8]: wikipedia :: Double-checked locking
От: $$ Австралия жж
Дата: 14.12.19 20:22
Оценка: -1
Здравствуйте, netch80, Вы писали:

N>>>До C++11 можно было платформенно-зависимые функции применять.

N>$>Ага, InterlockedExchange. Подзабыл уже.

N>При чём тут это? InterlockedExchange не имеет уже никакого смысла, если мы под мьютексом, который защищает доступ к переменной (и все участники соблюдают это). Он нужен, если мы стараемся обойти без мьютекса — но в этом случае в C++11 есть свой atomic_exchange.

N>Про платформенно-зависимые я имел в виду, что где-то pthread_mutex_lock, где-то WaitForSingleObject над мьютексом.

N>А вы таки путаетесь в самых основах, лучше повторить.


Really? А вам не мешало бы ещё раз перечитать ваше сообщение, на которое ч отвечал, и double check locking.

N>$>На Java достаточно volatile.


N>И снова мимо. Явовский volatile ближе всего к std::atomic<> load/store с memory_order_seq_cst.

N>Но он не даст защиты больше чем на одно чтение/запись. Аналог доступа под мьютексом — это synchronized.

Re[9]: wikipedia :: Double-checked locking
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 15.12.19 07:20
Оценка: +1
Здравствуйте, $$, Вы писали:

N>>А вы таки путаетесь в самых основах, лучше повторить.

$>Really? А вам не мешало бы ещё раз перечитать ваше сообщение, на которое ч отвечал, и double check locking.

Really? Реализацию синглтона на одном только InterlockedExchange — в студию.

N>>$>На Java достаточно volatile.

N>>И снова мимо. Явовский volatile ближе всего к std::atomic<> load/store с memory_order_seq_cst.
N>>Но он не даст защиты больше чем на одно чтение/запись. Аналог доступа под мьютексом — это synchronized.
$>

А по сути?
The God is real, unless declared integer.
wikipedia :: Double-checked locking
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 13.12.19 01:22
Оценка:
По мотивам одного из срачей
Автор: aik
Дата: 13.12.19
, я наткнулся на несколько озадачевшею меня реализацию Double-checked locking:
#include <atomic>
#include <mutex>

class Singleton {
 public:
  Singleton* GetInstance();

 private:
  Singleton() = default;

  static std::atomic<Singleton*> s_instance;
  static std::mutex s_mutex;
};

Singleton* Singleton::GetInstance() {
  Singleton* p = s_instance.load(std::memory_order_acquire);
  if (p == nullptr) {
    std::lock_guard<std::mutex> lock(s_mutex);
    p = s_instance.load(std::memory_order_relaxed);    // <- это
    if (p == nullptr) {
      p = new Singleton();
      s_instance.store(p, std::memory_order_release);
    }
  }
  return p;
}


В принципе всё логично и работать оно будет, но какой в данном случае смысл в std::memory_order_relaxed под мьютексом? Мьютекс же работает как барьер и в любом случае чтение пройдет как std::memory_order_acquire? Или я что-то путаю?
Отредактировано 13.12.2019 1:23 kaa.python . Предыдущая версия .
Re: wikipedia :: Double-checked locking
От: σ  
Дата: 13.12.19 01:56
Оценка:
KP>В принципе всё логично и работать оно будет, но какой в данном случае смысл в std::memory_order_relaxed под мьютексом? Мьютекс же работает как барьер и в любом случае чтение пройдет как std::memory_order_acquire? Или я что-то путаю?

Умение задавать вопросы в которых 100% ответа — это своего рода талант.
Re[2]: wikipedia :: Double-checked locking
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 13.12.19 02:00
Оценка:
Здравствуйте, σ, Вы писали:

KP>>В принципе всё логично и работать оно будет, но какой в данном случае смысл в std::memory_order_relaxed под мьютексом? Мьютекс же работает как барьер и в любом случае чтение пройдет как std::memory_order_acquire? Или я что-то путаю?


σ>Умение задавать вопросы в которых 100% ответа — это своего рода талант.


Re[2]: wikipedia :: Double-checked locking
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 13.12.19 06:16
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Это оптимизация. memory_order_relaxed -- самый дешёвый вид чтения. На x86 это просто считывание переменной. Поскольку оно происходит под мьютексом, никаких дополнительных гарантий не нужно.


Я немного о другом. Разве мьютекс не является одновременно барьером? Если он является таковым, то memory_order_relaxed в данном случае не вносит никакой оптимизации.

Если же утверждение выше не верно, то хотелось бы понять каким образом memory_order_relaxed привносит здесь оптимизацию?
Re[2]: А смысл?
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 13.12.19 08:54
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>Короче, за что боремся?


Да меня сама конструкция заинтересовала, вариант использования std::memory_order_relaxed. Так что можно считать это не вопросом про синглтон, а вопросом про std::memory_order_relaxed и мьютексы
Re[5]: wikipedia :: Double-checked locking
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 13.12.19 14:33
Оценка:
Здравствуйте, $$, Вы писали:

$>Здравствуйте, Шахтер, Вы писали:

Ш>>Я не понимаю, чего здесь не понятного? Для считывания атомика нужно вызвать load с флагом.


$>Почему бы обычный volatile не использовать?

Потому что volatile делает совсем не то, что надо.

$>Ведь буков меньше и на до- C++11 компиляторах соберётся.

До C++11 можно было платформенно-зависимые функции применять.
The God is real, unless declared integer.
Re[2]: wikipedia :: Double-checked locking
От: sergey2b ЮАР  
Дата: 13.12.19 15:33
Оценка:
Здравствуйте, netch80, Вы писали:

N>Acquire был раньше, когда мьютекс захватывался. А теперь можно, пока под мьютексом, прочесть максимально дешёвым и быстрым образом и не получить за это по рыжей морде каким-нибудь обгоном. Поэтому — relaxed.

N>Иначе бы получалось, что мьютекс уже захвачен, и снова вдруг подымается машина сериализации операций — а нафига собственно?

а где нибудь можно про это почитать в систематизированном виде ?
те не в викпедии
Re[7]: wikipedia :: Double-checked locking
От: reversecode google
Дата: 13.12.19 15:58
Оценка:
static Object gObj;
Re[6]: wikipedia :: Double-checked locking
От: $$ Австралия жж
Дата: 14.12.19 02:26
Оценка:
Здравствуйте, netch80, Вы писали:

N>До C++11 можно было платформенно-зависимые функции применять.

Ага, InterlockedExchange. Подзабыл уже.

На Java достаточно volatile.
Re[7]: wikipedia :: Double-checked locking
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 14.12.19 09:54
Оценка:
Здравствуйте, $$, Вы писали:

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

N>>До C++11 можно было платформенно-зависимые функции применять.

$>Ага, InterlockedExchange. Подзабыл уже.

При чём тут это? InterlockedExchange не имеет уже никакого смысла, если мы под мьютексом, который защищает доступ к переменной (и все участники соблюдают это). Он нужен, если мы стараемся обойти без мьютекса — но в этом случае в C++11 есть свой atomic_exchange.
Про платформенно-зависимые я имел в виду, что где-то pthread_mutex_lock, где-то WaitForSingleObject над мьютексом.

А вы таки путаетесь в самых основах, лучше повторить.

$>На Java достаточно volatile.

И снова мимо. Явовский volatile ближе всего к std::atomic<> load/store с memory_order_seq_cst.
Но он не даст защиты больше чем на одно чтение/запись. Аналог доступа под мьютексом — это synchronized.
The God is real, unless declared integer.
Re[5]: wikipedia :: Double-checked locking
От: PM  
Дата: 14.12.19 10:56
Оценка:
Здравствуйте, $$, Вы писали:

$>Здравствуйте, Шахтер, Вы писали:

Ш>>Я не понимаю, чего здесь не понятного? Для считывания атомика нужно вызвать load с флагом.


$>Почему бы обычный volatile не использовать? Ведь буков меньше и на до- C++11 компиляторах соберётся.

http://isvolatileusefulwiththreads.in/C++/
Re[5]: wikipedia :: Double-checked locking
От: reversecode google
Дата: 14.12.19 11:43
Оценка:
Здравствуйте, $$, Вы писали:

$>Здравствуйте, Шахтер, Вы писали:

Ш>>Я не понимаю, чего здесь не понятного? Для считывания атомика нужно вызвать load с флагом.


$>Почему бы обычный volatile не использовать? Ведь буков меньше и на до- C++11 компиляторах соберётся.

volatile это всего лишь директива компилятору не оптимизировать доступ к переменной, т.е. не кешировать
int a = 1;
while (a){}

компилятор может соптимизировать в регистры или стек и сделать
int b = a;
while (b){}

очевидно что с другого потока если изменить "a" то первый не увидит у себя в цикле изменения

а вот гарантии в каком порядке CPU изменят и увидят эти изменения "a" уже дает atomic
на всяких x86 платформах это не имеет особо значения
а вот на arm,ppc уже ой как актуально

а гарантии того что этот "a" не изменится другим треидом в ОС дают мютексы

иногда вместо мютексов используют синхронизации на atomic-ах, называется это уже lockfree программирование
Re[10]: wikipedia :: Double-checked locking
От: $$ Австралия жж
Дата: 16.12.19 00:54
Оценка:
Здравствуйте, netch80, Вы писали:

N>А по сути?


Попробуйте включить голову: до C++ 11 кто-то писал double check locking.



T* temp = 0;
InterlockedEchangePointer(&s_value, &temp);
T* value = temp;
InterlockedEchangePointer(&s_value, &temp);
if(!value) {
acquireMutex...
}
Отредактировано 16.12.2019 1:23 Артём . Предыдущая версия .
Re[11]: wikipedia :: Double-checked locking
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 16.12.19 06:44
Оценка:
Здравствуйте, $$, Вы писали:

N>>А по сути?


$>Попробуйте включить голову: до C++ 11 кто-то писал double check locking.

$>T* temp = 0;
$>InterlockedEchangePointer(&s_value, &temp);
$>T* value = temp;
$>InterlockedEchangePointer(&s_value, &temp);
$>if(!value) {
$>acquireMutex...
$>}

Вот именно, что acquireMutex. Всё равно без мьютекса не обошлись. И кому тут надо было включать голову, если в упор не видите в собственном коде?
The God is real, unless declared integer.
Re[12]: wikipedia :: Double-checked locking
От: Шахтер Интернет  
Дата: 16.12.19 07:02
Оценка:
Здравствуйте, netch80, Вы писали:

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


N>>>А по сути?


N>$>Попробуйте включить голову: до C++ 11 кто-то писал double check locking.


N>$>T* temp = 0;

N>$>InterlockedEchangePointer(&s_value, &temp);
N>$>T* value = temp;
N>$>InterlockedEchangePointer(&s_value, &temp);
N>$>if(!value) {
N>$>acquireMutex...
N>$>}

N>Вот именно, что acquireMutex. Всё равно без мьютекса не обошлись. И кому тут надо было включать голову, если в упор не видите в собственном коде?


Мьютекс можно заменить на спинлок, который реализуется на InterlockedIncrement/Decrement. Но это, конечно, извращение.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.