Комментарии 23
конструкцию until..end я убрал из языка
[...]
Представляет она из себя обычный цикл while, с отличием в том, что условие проверяется после выполнения итерации.Ещё в классическом Паскале (а м.б. ранее) были четко определены циклы с предусловием и постусловием.
while i<5 do P(i)
пока i<5 выполнять процедуру P. Сначала проверяется условие i<5, если оно не выпоняется, то P не будет вызвана ни разу.
repeat P(i) until i<5
а здесь сначала вызывается P, а только потом проверяется условие i<5, т.о. P всегда будет вызвана (минимум 1 раз).
Для этого мной в Mash был добавлен класс TCriticalSection.
И все? Ни семафоров, ни условных переменных (conditional variables), ни атомиков?
Как-то маловато.
Также возникли вопросы по примеру использования:
proc CriticalThreadedProc():
while true:
Sleep(3000)
CSect -> Enter() // рекурсия поддерживается? Т.е. если я уже лочил CSect в данном треде - сработает или зависнет?
// а если тут у нас злобный джуниор вписал return - кто будет секцию разлочивать?
CSect -> Leave()
gc() // а если в вызывающей функции есть временные переменные - все, им кирдык?
end
end
Да...
Последнее время немного играл с параллельным программированием в Java. И есть несколько скользких моментов в вашей реализации.
что произойдет при попытке двух потоков задать разное значение атомику? first come, first served?
в случае с критической секцией, что если необходимо дать возможность нескольким потокам одновременный доступ к критической секции?
как насчет коммуникации между корутинами?
и по последнему изменению do..while
->whilst
&& while..do
-> while
. в английском, "whilst" — абсолютно то же самое что и "while" (для native speaker'ов; только что уточнил). плюс, разница в двух символах — потенциальный источник примитивнейших ошибок набора текста, при этом разница в поведении — заметная.
2) Можно передать потокам указатель на класс крит. секции, либо объявить её, как глобальную переменную.
3) TAtomic, ThreadList, глобальные переменные, а также прочие решения на любой вкус и цвет.
Мне кажется, что путаницы не будет :)
По поводу атомика как раз непонятно, в какой очередности будет задано какое значение. Пример:
// bankAccount = 100;
- Жена, поток 1: bankAccount.set(50)
- Зарплата, поток 2:bankAccount.set(1500)
В зависимости от очередности, последствия могут быть плачевными ;)
- Жена, поток 1: bankAccount->set(bankAccount->get()-50)
- Зарплата, поток 2: bankAccount->set(bankAccount->get()+1500)
??
дык это не меняет сути вопроса ведь:
- поток 1: bankAccount->set(bankAccount->get() — 50) === bankAccount->set(100 — 50)
- поток 2: bankAccount->set(bankAccount->get() + 1500) === bankAccount->set(100 + 1500)
я и спрашиваю: как в этом случае будет разрешен конфликт? какой механизм синхронизации используется внутри атомиков?
для простоты, попробуйте вот такую программу (не знаю, скомпилится ли — ваш проект непонятно ни как собрать вообще, ни как собрать под OSX):
uses <bf>
uses <crt>
uses <threads>
proc addProc(x):
for (i ?= 0; i < 1000; i++):
x->set(x->get() + 1)
end
end
proc subtractProc(x):
for (i ?= 0; i < 1000; i++):
x->set(x->get() - 1)
end
end
proc main():
bankAccount ?= new TAtomic(0)
PrintLn("Initial bank account state:", bankAccount->get())
Async(addProc, bankAccount) // 1000
Async(subtractProc, bankAccount) // 0
Async(addProc, bankAccount) // 1000
Async(subtractProc, bankAccount) // 0
Async(addProc, bankAccount) // 1000
Async(addProc, bankAccount) // 2000
Async(subtractProc, bankAccount) // 1000
Async(subtractProc, bankAccount) // 0
PrintLn("Final bank account state:", bankAccount->get()) // а будет ли 0?
end
В java для этого есть операции getAndAdd, addAndGet и подобные. Как в этом языке не знаю но думаю можно добавить на уровне стандартной библиотеки.
Проект можно собрать используя fpc, либо lazarus. Для того, чтобы все заработало, как нужно — собираете svm, библиотеки, mashc и скидываете файлы в похожую, как на гитхабе (bin_w32) иерархию
А что происходит в первом примере с переменной i, новый поток захватывает её текущее значение? В этом случае какая часть контекста копируется в момент создания потока?
Mash: multithreading, coroutines, async & wait