169 похожих чатов

Люди. Такая вот ситуация, есть некие данные, доступ к которым

нужно сделать атомарным. Окай помещаем эти данные (назовем их A) в стейт GenServer.
Далее, другому процессу нужно прочитать A, обработать в зависимости от уже своих данных (назовем их B) и в зависимости от результатов обработки внести изменения в A. И все это надо сделать атомарно.
Получается, что для атомарности, надо передать данные B генсерверу хранящему в стейте данные A, а он уже сам проведет эти обработки и внесет изменения. Казалось бы круто, но беда в том, что данные B имеют достаточно большой объем и представляется нецелесообразным копировать их из процесса в процесс.
Неужто придется таки городить мютекс?

25 ответов

14 просмотров

Есть очень много способов решения этой проблемы: 1. Если B может хранить свои данные в области литералов (они очень редко меняются или их можно записать при компиляции), то можно в GenServer A передать анонимную функцию, которая приймет данные A и вернет их модифицированную версию. Копирования при этом не будет. 2. Можно использовать ETS для A с сериализацией доступа. Тогда B может прочитать, мутировать и записать изменения A. Но там может прийтись придумать механизм хендоффа таблицы (можно подсмотреть в коннекшин пулинге Ecto как это делается). 3. Можно сделать механизм блокировки на уровне генсервера, который позволит сделать checkout данных из A по похожему принципу с тем, как работает чекаут в коннешин пулинге. (Только нужно будет мониторить процесс который сделалю чекаут чтобы автоматически завершить лок если он крешнулся или подумать про то как процессы зависят в древе супервайзеров). Вообще задача слишком абстрактная, не понятно много - это как много, что за данные, насколько дорогие/долгие вычисления и т.п.

Некоторое подобие оптимистического лока можно организовать на ets: select_replace

Евгений- Автор вопроса
Andrew Dryga
Есть очень много способов решения этой проблемы: 1...

Все три способа мне известны. 3-й способ как раз и есть фактически мютекс. 1-й не подходит, данные меняются часто и засунуть их в литерал или в какой-нибудь :persistent_term тоже не ахти идея. Выбор между ets или даже mnesia (транзакций ради) и мютексами. Ну или чем-то еще чего я не знаю.

Andrew Dryga
Есть очень много способов решения этой проблемы: 1...

Почему первому способу нужно редко меняющиеся данные?

Źmićer Rubinštejn
Почему первому способу нужно редко меняющиеся данн...

Потому что :persistent_term для изменения данных должен сделать глобальный GC

Евгений- Автор вопроса
Źmićer Rubinštejn
Почему первому способу нужно редко меняющиеся данн...

В :persistent_term не рекомендуется пихать часто меняющиеся данные, нет?

Менеджер памяти внутри использует ссылки, так что скорее всего при передаче параметра копирования и не будет вовсе.

Евгений- Автор вопроса
Николай Епифанов
Менеджер памяти внутри использует ссылки, так что ...

Будет, еще как будет. У меня там нет бинарей вообще.

Николай Епифанов
Менеджер памяти внутри использует ссылки, так что ...

Только большие binary которые не помещаются в heap процесса

Сделать это неатомарно не позволит сама модель акторов. Вы хотите сериализуемость? Может она не так нужна и пойдёт модель консистентности помягче?

Евгений- Автор вопроса
Aleksey @cheatex
Сделать это неатомарно не позволит сама модель акт...

Еще как позволит. Прочитал данные, пока идет обработка другой процесс тоже прочитал. Потом первый записал, затем второй записал. Приплыли. Гонки завершились победой одного из процессов.

А не проще все необходимые данные перенести в один процесс чтобы обработать сразу в одном процессе, а не гонять туда-сюда лямбды или данные?

Николай Епифанов
А не проще все необходимые данные перенести в один...

Видимо есть код B который не зависит от А и наоборот

Евгений
Еще как позволит. Прочитал данные, пока идет обраб...

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

Евгений- Автор вопроса
Lama Lover
Ну, можно реализовывать чтение перед записью Проце...

А если не равны, то снова прочитал и опять обработал и попытался записать и так далее? :)

Евгений
А если не равны, то снова прочитал и опять обработ...

Да, оно так и работает. Понятное дело, что у этого способа есть свои ограничения, но он очень хорошо работает, когда память делят мало акторов, а операция очень резвая. А про то что операция может не завершиться — это возможно и с мьютексом, конечно же. Если есть вероятность что доступ очень частый, то нужно реализовать очередь задач

Евгений- Автор вопроса
Lama Lover
Да, оно так и работает. Понятное дело, что у этого...

Эм с мютексом-то как операция не сможет завершиться?

Евгений
Эм с мютексом-то как операция не сможет завершитьс...

Ну, актор хочет взять мьютекс, а он уже взят. Актор опять хочет взять мьютекс, а он уже взят И т.д. Типа в перерывах между попытками взять мьютекс, кто-то другой его отпускает и берёт

Евгений- Автор вопроса
Lama Lover
Ну, актор хочет взять мьютекс, а он уже взят. Акто...

Не обязательно, актор пытается залочить мютекс и блокируется пока мютекс не освободится.

Евгений- Автор вопроса
Lama Lover
А как он поймёт что мьютекс освободился?

Мютекс ему и сообщит, что теперь он овнер.

Евгений
Мютекс ему и сообщит, что теперь он овнер.

Так это и есть очередь задач. Просто ты не задачи посылаешь, а входишь в транзакцию. Идея паттерна очередь не меняется

Евгений- Автор вопроса
Lama Lover
Так это и есть очередь задач. Просто ты не задачи ...

По мне так это просто реализация мютекса. Можно спинлоками, можно очередями.

Похожие вопросы

Обсуждают сегодня

а через ESC-код ?
Alexey Kulakov
29
30500 за редактор? )
Владимир
47
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
13
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
program test; {$mode delphi} procedure proc(v: int32); overload; begin end; procedure proc(v: int64); overload; begin end; var x: uint64; begin proc(x); end. Уж не знаю...
notme
6
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
вы делали что-то подобное и как? может есть либы готовые? увидел картинку нокода, где всё линиями соединено и стало интересно попробовать то же в ddl на lua сделать. решил с ч...
Victor
8
Ребят в СИ можно реализовать ООП?
Николай
33
Подскажите пожалуйста, как в CustomDrawCell(Sender: TcxCustomGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean); получить наз...
A Z
7
Карта сайта