nextel
@nextel
ненавижу javascript

Почему filepath.Walk вешает весь скрипт намертво?

Здравствуйте, есть проблемный скрипт
Ссылка на плайграунд
в кратце что он должен делать
1. Запускается main
2. Создается отдельная горутина convert которая сидит и слушает канал чтоб взять оттуда обьекты и передать в функицю runconvert если есть обьект то увеличиваем counter на 1, если коунтер меньше 5 если больше ниче не делаем
3. запускаем в бесконечном цикле обход директории и всех поддерикторих которые были указаны при запуске первым аргументом.
4. функция filepath.Walk вызывает на каждый найденый файл walkfunc
5. Walkfunc в свою очередь создает обьект ипихает его в канал где его уже ждут.
6. функция runconvert "отрабатывает" и уменьшает counter на 1 и атк по кругу

все идет по плану 5-6 итераций а потом вешается намертво, при этом, если мы заменим filepath.Walk простым счетчиком допустим от 1 до 1000 создаем обьект и пихаем его в канал то отрабатывает все на ура. как мне это все пофиксить?

UPD: Каунтер нужен для того чтоб runConvert ов было НЕ БОЛЕЕ 5ТИ в одно время, потмоу что если горутинф бцдцт прсото хватить все что попадет в канал они их ранконвертов в скоре наплодят по количечеству файлов, а как написано в исходнике "имитация бурной деятельности" деятельность ествтельно бурная и если пладить беконтрольно то сервак повешается пока не разгребет все а если это 10000000 файлов я потеряю его не неделю нафиг)
  • Вопрос задан
  • 217 просмотров
Решения вопроса 1
Вы изменяете глобальную переменную counter из нескольких горутин одновременно, это не потокобезопасно.
Изменение счетчика на +1 или -1 это несколько действий на самом деле.
1. Прочитать значение.
2. Провести с ним операцию инкремента или декремента
3. Записать значение.
А теперь представим, что две горутины одновременно пытаются изменить значение счетчика. Счетчик сейчас равен 5 и горутины пытаются его уменьшить на единицу. Они обе прочитали себе значение 5, уменьшили его на 1, получилось 4, и обе записали 4. При правильной работе мы должны были бы получить 3, так как у нас завершились две runConvert, а получили 4.

Плюс, у вас будет зацикливание на for {} при counter>=5, которое потеснит в планировщике остальные горутины.

Зачем вам вообще этот counter, если есть замечательная вещь — каналы!
pastebin.com/714YTT8U
Нужно просто запустить 5 горутин через go converter() и с помощью каналов между ними будут прекрасно распределяться задачи.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Скорее всего не Walk вешается, а происходит взаимоблокировка канала.
Например, counter у вас меняется в разных горутинах. В этих случаях, надо использовать блокировки перед изменением с помощью mutex.Lock и Unlock. А так у вас в какой-то момент времени накопился counter> 10,
runConvert не очищает больше канал, а listFunc не может туда ничего писать.
И вообще, зачем counter вводить?
Просто

for {
go runConvert(<-sourceFileChan)
}

должно работать.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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