LINUX.ORG.RU

(пере-)синхронизация тредов с повторением порядка

 ,


0

1

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

Т.е. для каждого треда хочется такого:

while(true) {
   int id = get_seq_id();  # threadsafe, id монотонно возрастают
   compute(); # runs in parallel
   commit(id); # threadsafe, но в порядке возрастания id
   cleanup()
}

Пока в голову пришло только, что можно было в `get_seq_id` возвращать promise и помещать future от него в очередь на другом конце которой сидел бы отдельный поток, который и делал бы commit. Вроде бы должно работать, но надо заморачиваться с возвращением результата коммита обратно в каждый тред, это выглядит переусложненным, да и дергать контексты просто чтобы записать в файл в нужном порядке (commit именно это и делает) не выглядит как нечто хорошее.

В общем, можно ли обойтись без дополнительных тредов и какое слово гуглить для этого?

Предпочтительно Java/Scala, но не так важно, т.к. если найдется решение в других языках, то идля Java/Scala что-то подобное тоже будет.

Спасибо.

★★

Последнее исправление: redbaron (всего исправлений: 1)

Считающий семафор. Каждый тред на каждой итерации извлекает на один больше ресурс от предыдущего. А главный тред помещает туда 1 потом 2 итд ресурс. Работает, только скорость зависит от производительности семафора.

nanoolinux ★★★★
()

При первой синхронизации использовать счётчик, каждая нить запоминает свой порядковый номер. При второй синхронизации считать снова с нуля, но каждая нить будет ждать на переменной состояния своё значение счётчика.

kvap
()

Producers consumer же вроде как идеально подходит.

Один пул считает (у него две очереди in && out). Второй пул/поток читает исходящую очередь, просматривая её на пример того что появилась упорядоченная цепочка(до первого гэпа), которую можно покоммитать, что успешно и делает, до первого пропуска в цепочке сиквенсов.

Эвент луп примерно такой:

while(!break)
{
  seq_num_t seqNum = nextSeq();
  compute(seqNum);
  commit(seqNum);
  cleanup(seqNum);// Не понятен смысл сего метода, 
//но если тут имеется контекст, его надо хранить в мэпе видимо, и очищать после коммита
}

На азио, сиё пилится за полчаса, с перерывом на кофе и просмотр порно, без учёта бизнес логики конечно же. На Java/scala, тоже должно быть не сложно. Длительных блокировок будет заметно меньше, чем если управлять порядком выполнения самих тредов.

Про Future, сначала не прочитал, начал распинаться, но в принципе почему нет.

Ещё я вроде слышал, что posix_threads таки позваляют и такое извращение, но где пока чет не вспомнил.

pon4ik ★★★★★
()
Ответ на: комментарий от post-factum

С другой стороны, товарищь kvap выше предложил фактически барьер, со слегка изменённым условием, который решает задачу во всех её проявлениях. Вопрос только важен ли порядок вычислений, или только порядок коммитов. Если только коммитов, то моё предложение будет пошустрее работать, и меньше зависеть от причуд планировщика, иначе оно вообще не сработает, без точно такого же барьерчика, что делает его ненужным:)

pon4ik ★★★★★
()

Ticket lock.

mv ★★★★★
()

Очевидно, запомнить где-то последовательность последовательность тредов. Потом, при вызове коммита:
если этот коммит в нужном порядке, то коммитить,
иначе поместить его в пециальный список-кеш и хранить его пока кусок кеша не упорядочится другими тредами.

four_str_sam
()
Ответ на: комментарий от kvap

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

Я пытаюсь разбить лок в существующей системе, в которой треды из пула воркеров периодически сидят и ждут друг-друга, хотя строгая очередность нужна только на двух самых дешевых этапах - получить порядковый номер и записать в файл, а сами вычислеиния между ними можно распаралеллить.

redbaron ★★
() автор топика
Ответ на: комментарий от redbaron

Что значит «разом приступают» и «разом заканчивают»?

kvap
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.