LOCK в многопотоке

Поддержка
  • @denis_krsk said in LOCK в многопотоке:

    данные взять и обработать можно

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

  • @denis_krsk Вы же FIFO буфер для записи из разных потоков с асинхронными действиями не сможете реализовать в БАСе?

  • @senerg said in LOCK в многопотоке:

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

    Вы сами то поняли что написали? Чем ваши асинхронные действия помешают увеличивать глобальную переменную?

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

  • @senerg said in LOCK в многопотоке:

    @fox , @Denis_krsk , @xclsv
    Например, в нескольких потоках делаю гет запрос, пересчитываю количество ссылок, которые есть в ответе, увеличиваю глобальную переменную на это количество.

    То, для чего Вы пытаетесь придумать велосипед, делается иначе. Сначала в однопотоке пересчитывается количество ссылок. Затем в многопотоке эти ссылки обрабатываются.

    @senerg said in LOCK в многопотоке:

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

    Многопоточность есть. Просто она работает не так, как Вы себе это представляете. При этом Вы не ещё даже не пытались подумать, с какими проблемами столкнётесь, если она будет работать именно так, как Вам нужно.
    Проблем не в бас и его функционале, а в том, что Вы не придумали алгоритм и не предусмотрели обработку ошибок, которые будут возникать при его реализации.

  • @xclsv said in LOCK в многопотоке:

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

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

    @denis_krsk said in LOCK в многопотоке:

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

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

  • @senerg

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

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

    Да!

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

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

  • @senerg said in LOCK в многопотоке:

    Я же не говорю, что бас вдруг стал плохим

    Да, но Вы пишете, что в бас нет многопоточности. Она есть.

  • @xclsv , она есть, но с ограничениями. Вы не можете создавать новый поток когда вам вздумается. Вы не можете запустить в многопотоке функцию, в которой между чтением и записью в глобальную переменную есть асинхронное действие. И еще наверняка много других ограничений, о которых я пока не знаю. Есть так как есть, и огромная благодарность автору баса за то, что есть хоть так. Даже в текущем воложении этого более чем достаточно для 90% задач.
    Я лишь говорю о том, что нет мануала о том что можно, что нет. И пока сам носом не натыкаешься на все эти особенности о них и не узнаешь.

  • @senerg said in LOCK в многопотоке:

    Вы не можете создавать новый поток когда вам вздумается

    Да, действия new Thread() в BAS'e из коробки пока нет.

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

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


    Представьте ведро
    0_1542105445958_84c8469d-6084-4699-8115-12f726215add-изображение.png
    В него не глядя накладывают раствор 5 строителей, если строитель будет смотреть в ведро сразу как положил в него раствор, он будет всегда знать, сколько его сейчас в ведре.

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

  • @senerg said in LOCK в многопотоке:

    @xclsv , она есть, но с ограничениями. Вы не можете создавать новый поток когда вам вздумается. Вы не можете запустить в многопотоке функцию, в которой между чтением и записью в глобальную переменную есть асинхронное действие. И еще наверняка много других ограничений, о которых я пока не знаю. Есть так как есть, и огромная благодарность автору баса за то, что есть хоть так. Даже в текущем воложении этого более чем достаточно для 90% задач.
    Я лишь говорю о том, что нет мануала о том что можно, что нет. И пока сам носом не натыкаешься на все эти особенности о них и не узнаешь.

    Я так понял, Вы решаете задачу парсинга неизвестного количества страниц. Что мешает посчитать их количество и потом распределить в многопотоке? Не нужно будет пользоваться глобальными переменными. Не нужно будет заморачиваться с добавлением потока и асинхронными действиями. К тому же это намного эффективнее и по времени и по ресурсам. Уже предлагал это в соседней теме, может не увидели.

  • @fox Я не знаю что вы понимаете под словом "асинхронные", но я понимаю вот это, а не ведро.

    @xclsv said in LOCK в многопотоке:

    Вы решаете задачу парсинга неизвестного количества страниц. Что мешает посчитать их количество и потом распределить в многопотоке?

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

  • @senerg said in LOCK в многопотоке:

    Чтобы узнать количество нужно сделать запрос на страницу и в ответе посмотреть пришла ли нужная страница (или есть ли кнопка перехода на следующую страницу)

    Совсем не обязательно.
    Вы можете делать запрос не к каждой странице, а, к примеру, через каждые 100 страниц. Затем уменьшать интервал вдвое каждый раз, когда ответа не будет и откатываться назад. Этот метод называется "делением отрезка пополам". Он откровенно неэффективен лишь когда у вас будет 1 страница.
    Кстати, иногда на пустые страницы серверы отдают ответ 404. Это означает, что не обязательно смотреть и парсить весь ответ. Достаточно проверить статус ответа.
    Почти все пагинаторы на сайтах написаны по какому-то алгоритму. Вы можете спарсить с первой страницы количество товаров. Зная число товаров на одной странице можно вычислить число страниц.
    У меня была ситуация, когда пагинатора не было и никак нельзя было спарсить число страниц. Вычислять по каким-то причинам тоже было невозможно. Пришлось применить военную хитрость. Я просто парсил страницы подряд, проверяя, есть ли на них данные. Если нет, поток фейлился с запретом перезапуска. Профит. В этом случае, чисто лишних запросов будет равно числу потоков. Вероятно, они будут содержать пустые ответы. Не вижу проблемы в их наличии. Обойти это можно через Прервать скрипт без галочки Мгновенное завершение. Но это не очень удобно, ибо скрипт завершится полностью, хоть и подождёт завершения каждого потока. Полагаю, функцию, вызванную в многопотоке так остановить не получится.
    Но и это не всегда работает. Вообще, нужно смотреть конкретную ситуацию. Скиньте ссылку, откуда надо спарсить число страниц. Попробуем определить оптимальный алгоритм.

  • @xclsv said in LOCK в многопотоке:

    Зная число товаров на одной странице можно вычислить число страниц

    Не выйдет. На некоторых страницах али вставляет рекламный товар в списке выдачи. На одной странице 48 товаров, а может быть 47 если рекламный товар будет на странице.
    Я делаю парсер для любой страницы выдачи али. Пока план такой: запускать 100 торов по одному для каждого потока, затем в одном потоке загружать первую страницу, получать с нее 48 урлов на товары и, получив ссылку на вторую страницу, составить список ссылок на все 100 страниц выдачи. Затем запустить в 100 потоках парсинг каждой страницы (3 гет запроса в трех потоках на товар), с выводом данных в глобальный список с индексом 1+48*page_index, после удалить из него пустые строчки, которые появятся из-за возможного появления рекламного товара на странице.
    Не знаю только на сколько али понравится около 1000 запросов в секунду, есть у вас опыт с парсерами?

  • @senerg
    Если отправить запрос на страницу номер 9999, которой нет, что отдаст Али?

  • @senerg
    Нашел решение для Вас.
    Делаете один запрос к странице №100500. Автоматически попадёте на последнюю, откуда и спарсите количество страниц рубрики.

  • @xclsv said in LOCK в многопотоке:

    Делаете один запрос к странице №100500. Автоматически попадёте на последнюю, откуда и спарсите количество страниц рубрики.

    С чего вы это взяли?
    Вот вторая страница
    Вот 100500
    Вы про скорость парсинга не знаете? Думаю 1000 в секунду не стоит, а то обвинят в ддос атаке)

  • @senerg said in LOCK в многопотоке:

    С чего вы это взяли?
    Вот вторая страница
    Вот 100500

    С того что снифал запрос не с параметром страницы браузера, а запрос к странице через "перейти к странице" в правом нижнем углу экрана.
    0_1542190891262_6716010d-6646-4fc1-8bad-773b81ab66a2-image.png
    В ответ сервер али редиректит на последнюю или на 100 страницу(смотря что меньше).

    @senerg said in LOCK в многопотоке:

    Вы про скорость парсинга не знаете? Думаю 1000 в секунду не стоит, а то обвинят в ддос атаке)

    Али выдержит и 1кк запросов в секунду без проблем. Если будет блок по ip - добавьте прокси.
    А вообще, беспокойство за бан чуток противоречит политике разработки многопоточных скриптов =)

  • @xclsv said in LOCK в многопотоке:

    Али выдержит и 1кк запросов в секунду без проблем. Если будет блок по ip - добавьте прокси.
    А вообще, беспокойство за бан чуток противоречит политике разработки многопоточных скриптов =)

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

  • @senerg said in LOCK в многопотоке:

    Думаю, что качать с них 100 мегабит будет палевно, даже если прокси постоянно менять

    Пусть будет по-вашему.