LINUX.ORG.RU

Data race

 ,


0

2

Санитайзер говорит о рейсах здесь, объясните мне пожалуйста - что здесь не так? Всё под мьютексом.

#include <mutex>
#include <thread>
#include <chrono>
#include <condition_variable>
#include <queue>
#include <memory>
using namespace std;

struct Mes {
	int data = 0;
	bool processed = false;
};

struct Test {
	mutex mtx;
	condition_variable cv;
	queue<weak_ptr<Mes>> mes_queue;
	int read();
	bool check();
} t;

int Test::read()
{
	auto sh_ptr = make_shared<Mes>();
	unique_lock lck{mtx};
	mes_queue.push(sh_ptr);
	while (! cv.wait_for(lck, 1s, [&sh_ptr](){
				return sh_ptr->processed == true;})  &&  true);
	return sh_ptr->data;
}

bool Test::check()
{
	scoped_lock lck{mtx};

	bool ret = mes_queue.size();
	while (mes_queue.size()) {
		if (shared_ptr<Mes> mes = mes_queue.front().lock()) {
			mes->data = 5;
			mes->processed = true;
		}
		mes_queue.pop();
	}
	cv.notify_all();
	return ret;
}

void read_th() {
	while (true) {
		t.read();
		this_thread::sleep_for(200ms);
	}
}

void check_th() {
	while (true) {
		t.check();
		this_thread::sleep_for(200ms);
	}
}

int main() {
	jthread tr{read_th};
	jthread tc{check_th};
}

$ g++ -pthread -std=c++20 -fsanitize=thread test.cc

Выхлоп санитайзера весьма обилен, вставил сюда, но главное то, что жалобы на рейсы в полностью валидном коде (на мой взгляд).

★★

Ответ на: комментарий от Elyas

Блокирует, это 100%, в справочнике смотрел, там для отложенного лока надо передать defered_tag передать.

Надо понять - я не умею многопоток и надо идти читать, или санитайзер такой хороший.

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

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

kvpfs ★★
() автор топика

Немного о дизайне - почем weak_ptr в очереди сообщений? Есть главный поток, который обрабатывает сообщения от внешних потоков, которые пихают в queue свои запросы, главный отвечает. Внешние потоки могут (в зависимости от некоторых условий) перестать ожидать ответа и уйти из цикла ожидания, следовательно, вик_птр не сделает шаред_птр, главный поток расценит сообщения как невалидное и проигнорит.

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

А вот замена mutex и condition_variable на recursive_mutex и condition_variable_any влияет - рейсы исчезают (но другие жалобы есть, менее серьезные). Я буду копать выхлоп, разные там verbose флаги санитайзеру давать, но я пока даже близко пока не могу понять почему такая петрушка.

kvpfs ★★
() автор топика
Последнее исправление: kvpfs (всего исправлений: 2)

Санитайзер жалуется на double lock следующим образом (стек вызовов):

WARNING: ThreadSanitizer: double lock of a mutex (pid=74462)
    ...
    #4 std::unique_lock<std::mutex>::unique_lock(std::mutex&) <null> (a.out+0x4a32)
    #5 Test::check() <null> (a.out+0x2628)
    #6 check_th() <null> (a.out+0x27d7)
    ...

    ...
    #4 std::unique_lock<std::mutex>::unique_lock(std::mutex&) <null> (a.out+0x4a32)
    #5 Test::read() <null> (a.out+0x24d0)
    #6 read_th() <null> (a.out+0x277a)
    ...

очевидно, что check_th() и read_th() выполняются в разных потоках, откуда там может быть double lock?

kvpfs ★★
() автор топика
Последнее исправление: kvpfs (всего исправлений: 1)

clang++ ничего не вывел. Так что может быть и баг в gcc.

Репорть им.

В любом случае у кого-то баг, или в gcc или в clang

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

Кстати, совсем разочаровался в clangd (комплит и все смежные плюшки для удобства). Он у меня сейчас на проекте просто тупо падает на самом запуске и всё. Когда код был чуть проще, то работал паршиво, но хоть на объявление можно было прыгнуть частенько, сейчас же вообще помер. От стандартного вимовского комплита много больше толку, чем от шлангового. Надо переходить на какие-нибудь таги.

kvpfs ★★
() автор топика

Ещё там какие-то траблы с condition_variable, такой коде:

fn()
{
	using namespace std::literals::chrono_literals;

	auto sh_ptr = std::make_shared<Get_data_message<column_number>>();
	if (! m_shared.suspend_request.test(std::memory_order_relaxed)) {
		std::unique_lock lck{m_shared.mtx};
		m_shared.mes_queue.push(sh_ptr);
		//while (! m_shared.cv.wait_for(lck, 1s, [&sh_ptr](){
		//			return sh_ptr->processed == true;})  &&
		//	! m_shared.suspend_request.test(std::memory_order_relaxed));
	}
}

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

А можно как-то поставить в игнор одну функцию и не генерить для неё обвязку для санитайзера? Чтобы была возможность хоть что-то проверить, а так выхлоп из этого санитаро-багнутого места всё загадит.

kvpfs ★★
() автор топика
Последнее исправление: kvpfs (всего исправлений: 1)

scoped_lock lck{mtx};

это какое-от новье от C++20? почему параметр у конструктора в фигурных скобках? почему не scoped_lock lck(mtx);

alysnix ★★★
()

если делать человечно, то надо просто писать темплейт тредсейф очереди обьектов общей стратегии - много тредов кладут, много тредов берут, делать все операции типа get(…) с таймаутами, на put(…) таймауты необязательны, но желательны, если контролировать, чтобы очередь не перполнялась - то есть попытка положить в переполненную очередь должна блокировать тред с таймаутом.

и потом от этого темплейта порождать конкретные очереди. впрочем это уже написано тыщупицот раз.

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

вообще-то нормальный многопоток пишется на правильных абстаракциях синхронизации, а не тех примитивах что дает системная либа с++. она скорее предназначена для реализации правильных абстракций, а не непосредственного применения.

а правильных абстракций всего три

  • рекурсивный мьютекс с таймаутом

  • канал (он же вышеупомянтуая очередь много кладут-много берут)

  • и «флаг» - то есть обьект ожидания на который встает тред и ждет когда другой тред флаг поднимет(ну или опустит). или более общий случай флага - семафор в его традиционном толковании. естессно все ожидания с таймаутом.

а вот эту ерундистику в кондварами и мьютексами в конвенциональном коде писать не надо. это надо один раз в либе какой-нить написать, внутри реализации очереди, и больше не писать никогда.

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

а правильных абстракций всего три

Н-да. А народ то и не знал. И заморачивается иногда со всякой хренью типа lock-free / wait-free…

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

И заморачивается иногда со всякой хренью типа lock-free / wait-free…

а народ чем только не заморачивается!

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

а правильных абстракций всего три

lock-free / wait-free

Это не абстракции, это гарантии реализации (абстракций)

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

а правильных абстракций всего три

lock-free / wait-free

Это не абстракции, это гарантии реализации (абстракций)

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

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 1)
Ответ на: комментарий от bugfixer

мьютексом и семафором

Ну а вдруг (сделают ЯП, платформы, системы, где) эти абстракции церокост :wow:

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

Это не абстракции, это гарантии реализации (абстракций)

это вредная попытка оказаться от синхронизации вообще. а не правильные абстракции синхронизации.

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

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

правильные абстракции синхронизации.

То, что ты предложил, это «необходимый и достаточный»(?) набор примитивов синхронизации. Эти наборы могут быть другие и правильные - «необходимые и достаточные».

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

Эти наборы могут быть другие и правильные - «необходимые и достаточные».

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

нерекурсивный мьютекс - это частный случай семафора.

но и семафор можно симулировать короткой очередью, это конечно не так эффективно, как сам семафор.

ps:

ну предложи другой минимальный и ортогональный набор примитивов синхронизации. готов обсудить. но именно ортогональный и минимальный.

pss: а что касается кондвара - это примитив изобрели ТОЛЬКО ради того, чтобы правильно реализовать очередь. поскольку ТОЛЬКО эта штука дает возможность АТОМАРНО разлокнуть мьютекс и встать в ожидание. другой такой возможности нет. потому и надо сразу делать темплейт очереди и больше с кондварами не париться.

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

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

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 4)
Ответ на: комментарий от alysnix

необходмый и достаточный - очередь и рекурсивный мьютекс

И как, от дедлоков спасает? Или все таки недостаточный.

Тем временем есть набор, который используется в lock-free алгоритмах, где нет дедлоков, зато есть зацикливание.

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

И как, от дедлоков спасает? Или все таки недостаточный.

от дедлоков не спасает ничто, кроме правильной архитектуры. дедлок, это когда как минимум два треда, неверно захватывают, как минимум два мьютекса. в неверном порядке. причем функции захвата у них без таймаута(а я про таймауты ОСОБО указал!). если есть таймаут на захват, что дедлока очевидно не будет. и вариант вохможного дедлока, в виде слишком долгого(выбор разработчика) ожидания освобождения мьютекса обрабатывается программно. то есть прога ругается и вполне управляема. а разраб должен устранить эту проблему.

а зацикливание хуже дедлока.

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

а зацикливание хуже дедлока.

Лучше мертый, чем живой. За мертвого награда больше.

anonymous
()
Ответ на: комментарий от alysnix

ну предложи другой минимальный и ортогональный набор примитивов синхронизации. готов обсудить. но именно ортогональный и минимальный.

CAS + atomics + memory barriers. Всё. Причём даже понятно в какой asm оно разворачивается. Все примитивы которые Вы перечислили довольно высокоуровневые и построены поверх этого. Да да, именно так устроен этот мир.

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

CAS + atomics + memory barriers.

треды-то тут где? единицей исполнения в многопотоке(он потому и называется многопоток) является тред. то есть поток.

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

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

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

cas(compare and swap??) - частный случай атомарной операции.

что вообще можно на этом программировать?

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

кстати, с помощью перечисленных вами базовых абстракций нельзя реализовать модель тредов. потому что упущена еще одна «абстракция» - механизм прерываний. потому что, чтобы защитить код на совсем нижнем уровне - атомиков и барьеров недостаточно. нужно еще и управлять прерываниями.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 3)
Ответ на: комментарий от alysnix

треды-то тут где?

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

что вообще можно на этом программировать?

Господи, как всё запущено то… Вы бы постеснялись хотя бы такой бред на весь мир озвучивать.

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

напишите код простейшего шедулера переключающего треды. и все станет понятно.

(а) зачем? давно уже всё написано и лучше я вряд ли сделаю. (б) что именно мне должно стать понятно? (в) много много лет назад я тоже был очень молод и очень неопытен, и тыкал мьютексы везде где ни попадя (например в свои shared_ptr), а потом пришло осознание того как это взрослые дяденьки делают, зачем и почему. Рекомендую Вам покопаться в более-менее профессионально написанном коде, крепко поразмышлять, и только потом начинать нести свои «идеи» в массы.

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 1)
Ответ на: комментарий от bugfixer

Рекомендую Вам покопаться в более-менее профессионально написанном коде, крепко поразмышлять, и только потом начинать нести свои «идеи» в массы.

отсутствовал по обстоятельствам непреодолимой силы. с собачкой гулял. придумал простейшую задачку на мультитред. тред А запускают и он пишет - «я тред А» и заканчивается. тред Б запускают и он пишет - «я тред Б» и заканчивается.

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

на экране должно быть написано сначала - я тред А, потом - я тред Б.

на том наборе что предлагаю я (мьютекс+очередь) это пишется так:

Queue<int> q; //очередь интов

тело треда A:
{
  print("Я тред А");
  q.put(666); ///кладет нечто в очередь
}

тело треда Б:
{
  int i = q.get(); ///тред ждет когда в очередь что-то положат.
  print("Я тред Б");
}

с семафорами будет еще легковесней, но у нас минимальный набор, и семафора как бы нет.

итак, напишите плиз , как это надо решить взрослодядечно и профессионально, на атомиках и барьерах.

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

итак, напишите плиз, как это надо решить взрослодядечно и профессионально, на атомиках и барьерах.

Имеем в ring buffer позицию писателя и читателя (желательно в разных концах чтобы оно лежало в разных cachelines). Писатель кладёт данные в буфер, memory barrier, изменяет свою позицию (на x86 naturally-alligned memwrites до 8 байт atomic). Будит читателя (как это сделать - это отдельный вопрос, он вовсе не обязан спать на conditional variable, и вообще в случае SHM быть в том же процессе. Читатель забирает данные, изменяет свою позицию, memory barrier. Что делать писателю если читатель не успевает - тоже отдельный вопрос, стратегии могут быть разными. Как-то так.

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

Будит читателя (как это сделать - это отдельный вопрос, он вовсе не обязан спать на conditional variable, и вообще в случае SHM быть в том же процессе. Читатель забирает данные, изменяет свою позицию, memory barrier. Что делать писателю если читатель не успевает - тоже отдельный вопрос, стратегии могут быть разными. Как-то так.

это называется суп из топора. вы это напишите в псевдокоде хоть…

а будит и встает в ожидание - это вопрос не отдельный, а принципиальный! потому, что это основной вопрос философии тредов.

а в ваших концепциях об этом нет НИЧЕГО. ни одна из ваших базовых штучек, этого делать не умеет. я потому и говорю, что в ваших понятиях ничего написать невозможно, потому что нет ни треда, ни ожидания, ни пробуждения, ни переключения.

ну вот что значит в ваших словах - «читатель забирает данные»? а пока данных не было, читатель делал что? спал, в цикле крутился? если спал - как он заснул и как пробудился?

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

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

С помощью твоих «очереди и мьютекса» тоже. Потому, это абстракции поверх твоей «модели тредов».

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

С помощью твоих «очереди и мьютекса» тоже. Потому, это абстракции поверх твоей «модели тредов».

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

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

я потому и предположил, что возможно автор предложения хочет поверх «барьеров и атомиков» реализовать нормальные треды?

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

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

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 2)
Ответ на: комментарий от alysnix

очередь и мьютекс - неопределены как понятия.

Нет, в твоей «модели тредов» они должны быть определены. Мьютекс без определения как он взаимодействует с тредом, с планировщиком, и еще много с чем, о чем ты забыл упомянуть - это бессмысленный термин.

Ты либо объясняй свои «мьютексы с очередями» в терминах задачи обедающих философов, либо не требуй от собеседника объяснять современную архитектуру вычислительных систем.

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

Нет, в твоей «модели тредов» они должны быть определены. Мьютекс без определения как он взаимодействует с тредом, с планировщиком, и еще много с чем, о чем ты забыл упомянуть - это бессмысленный термин.

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

это что писано мной ранее?

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

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

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

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

Осталось найти эти абстракции в современных вычислительных системах. Как же они работают с потоками без твоих правильных абстракций? Или там другие правильные абстракции?

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

Осталось найти эти абстракции в современных вычислительных системах. Как же они работают с потоками без твоих правильных абстракций? Или там другие правильные абстракции?

в «современных вычислительных системах» потоки и всякие мутексы, кондвары и прочее, реализованы в кернеле и интерфейс к ним торчит наружу в виде стандартной плюсовой библиотеки(например), или каких-нить posix threads. мы вообще-то про С++ счас говорим.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

в «современных вычислительных системах» потоки и вся мутексы реализованы в кернеле

В каком кернеле? В некоторых ОС нет понятия потока вообще, разве что процессы и межпроцессное взаимодействие и никаких мутексов, семафоров, разве что очередь сообщений.

мы вообще-то про С++ счас говорим

Ты о чем только не говоришь.

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

В некоторых ОС нет понятия потока вообще, разве что процессы и межпроцессное взаимодействие и никаких мутексов, семафоров, разве что очередь сообщений.

значит эти ос не соответствуют модели posix.

зачитываю из википедии с выражением(если кому лень самому посмотреть)

POSIX Threads — стандарт POSIX-реализации потоков (нитей) выполнения. Стандарт POSIX.1c, Threads extensions (IEEE Std 1003.1c-1995) определяет API для управления потоками, их синхронизации и планирования.

Реализации данного API существуют для большого числа UNIX-подобных ОС (GNU/Linux, Solaris, FreeBSD, OpenBSD, NetBSD, OS X), а также для Microsoft Windows и других ОС. 

Ты о чем только не говоришь.

ну если «некоторая ос» не позволяет реализовать треды и все такое, из стандартной библиотеки C++, значит плюсы там не реализуемы в полном обьеме… непонятно только, кому от этого хуже. плюсам или этой ос.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

не соответствуют модели posix

Это достижение и провал?

Кстати, во всяких СУБД (блокировщиков и версионников) тоже есть конкурентное взаимодействие, где нужна синхронизация. Туда тоже posix threads тащить?

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

Это достижение и провал?

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

позикс треды и прочие позиксы - это для переносимости придумано, а не просто так.

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

провал конечно

Настанет мода на всякие async’и с иммутабельными типами данных, где будут другие «правильные примитивы», или какая-нибудь транзакционная память. Тогда что делать? Предать анафеме позикс-треды?

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

Настанет мода на всякие async’и с иммутабельными типами данных, где будут другие «правильные примитивы», или какая-нибудь транзакционная память. Тогда что делать? Предать анафеме позикс-треды?

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

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

вы совершаете непозволительную ошибку сводя концепцию тредов

Я даю другие примитивы вместо позикс-тредов: задачи, асинхронный вызов и ожидание. Это «правильные примитивы»?

А ты цепляешься к просто так сказанной «транзакционной памяти», которая как еще один пример, когда не нужны примитивы синхронизации при доступе к данным.

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

задачи, асинхронный вызов и ожидание

сначала надо сформулировать что такое «задача» и «ожидание». если у «задачи» есть свой контекст исполнения - то это просто тред.

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

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

короче, это все те же треды, только мехом внутрь.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.