ещё много много раз - потокобезопасные операции, Потокобезопасность.
Пользователь
Сообщений: Регистрация: 09.05.2015
13.05.2015 17:01:26
Знаю что много об этом сказано! Знаю что специально сделали потокобезопасные операции с приставкой s или с не важно.. Если сам не специалист в этой области приходится обращаться... На конкретных примерах ОБЩЕГО вида. -------------------------------------------- 1. это небезопасно! A={} function OnAllTrade(alltrade) table.insert(A, alltrade) end
function main() Table={} Table=A[1] end -------------------------------------------- 2. А это безопасно? если нет то почему?
A,B={},{} function OnAllTrade(alltrade) table.insert(A, alltrade) B=A end
function main() Table={} Table=B[1] end ------------------------------------------ 3. аналогично? A=0 function OnAllTrade(alltrade) table.insert(A, alltrade) A=A+alltrade.price-const_1+const_2+... end
function main() C=A/100 if C>const_N then ... end end ------------------------------------------ 4. ....? A=0 function OnAllTrade(alltrade) table.insert(A, alltrade) A=A+alltrade.price-const_1+const_2+... B=A end
function main() C=B/100 if C>const_N then ... end end ---------------------------------------- 5. функция getQuoteLevel2(class,sec) и т.п. вставленная внутрь main безопасна, не изменится ли таблица в процессе присваивания(чтения)? если нет то почему? что такое хэш и в чём отличие от массива? ------------------------------------ 6. Прошу, если это возможно, провести маленькую лекцию или дать ссылку где почитать о работе терминала в плане обработки поступающей информации и взаимодействии скрипта lua с той информацией что поступила в quik. Ясно что вот колбэк он вызывается при изменениях.. НО более подробно в доступной форме, что находится в "чёрном ящике"? Что там за информационные очереди, как они меняются, почему двигаемся по этой очереди, как к этой очереди подвязываются колбэки и main...Вот такого плана... Пожалуйста! Очень прошу, потому как ни чего не понятно...
Michael Bulychev
Гость
14.05.2015 13:24:02
Добрый день. 1 Да, это не безопасно. можете получить что в A[1] == nil
2. Если A и B таблицы, то B=A не копирует содержимое таблиц, а присваивает ссылку на таблицу A в переменную B, и все изменения в A отражаются в B. Далее аналогично п. 1
3 и 4 Примеры не очень понятны. A это таблица или переменная со значением ноль?
5. getQuoteLevel2 всегда возвращает текущий слепок стакана. Что значит "процесс присваивания чтения" не совсем понятно, поясните.
Пользователь
Сообщений: Регистрация: 09.05.2015
14.05.2015 16:19:19
2. Я правильно понял что фактически меняя таблицу А я одновременно буду менять B за счёт того что В есть просто ссылка на A. А если я сделаю пустую операцию над А и приравняю В к этому. Например что то вроде
function copy_(a) return a end function OnAllTrade(alltrade) table.insert(A, alltrade) B=copy_(A) end
function main() Table={} Table=B[1] end
В 3 и 4 извините поторопился забыл удалить строчку при копировании. Имеются ввиду обычные числовые переменные. Соответственно вроде бы обычные переменные можно то же одновременно модифицировать в колбэке и читать в main() и вроде может получиться в результате ерунда неизвестного вида. Что мешает этому?
Насколько я понял из старого форума проблема только в table.insert. Так вот чем table.insert отличается от обычных операций допустим сложения умножения (вроде бы то же модификация). И чем таблицы при модификации отличаются от простых переменных?
Пользователь
Сообщений: Регистрация: 09.05.2015
14.05.2015 16:22:09
Приведите пожалуйста потокобезопасные операции, с небольшими пояснениями!
Пользователь
Сообщений: Регистрация: 09.05.2015
16.05.2015 10:13:29
Что то я совсем запутался. Следуя вашим словам B={9,4,3,8} C=B таблица C это только ссылка на таблицу B тогда есть разница между записями а) C[1]=C[1]/2; table.sort(B) б) table.sort(B); C[1]=C[1]/2 Это так? И на предыдущие вопросы ответ те пожалуйста!?
Michael Bulychev
Гость
18.05.2015 09:48:34
Добрый день. В терминале обеспечивается физическая целостность данных. В случае с обычным присвоением a = b проблем нет - вы не сможете получить неопределенное значение переменной a. Либо значение до присвоения, либо после. В случае с table.insert проблема в том, что это не "атомарная" операция, а целая функция. которая делает следующее:
Michael Bulychev
Гость
18.05.2015 10:26:18
Добрый день. В терминале обеспечивается физическая целостность данных. В случае с обычным присвоением a = b проблем нет - вы не сможете получить неопределенное значение переменной a. Либо значение до присвоения, либо после. В случае с table.insert проблема в том, что это не "атомарная" операция, а целая функция, которая делает следующее: - все элементы с индексом больше либо равным заданному получают индексы на единицу больше; - указанный элемент вставляется по заданному индексу; Обращение в момент выполнения функции к элементам таблицы может привести к неопределенной ситуации. Для этого были сделаны потокобезопасные функции - получить доступ к таблице можно лишь после завершения их работы.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
18.05.2015 11:02:44
Цитата
Michael Bulychev пишет: Для этого были сделаны потокобезопасные функции - получить доступ к таблице можно лишь после завершения их работы.
Поподробнее пожалуйста. Это значит, что при обращении к таблице из другого потока текущая операция будет приостановлена до окончания обновления таблицы?
Надо делать так, как надо. А как не надо - делать не надо.
Michael Bulychev
Гость
18.05.2015 11:07:03
Да, если таблица глобальная.
Пользователь
Сообщений: Регистрация: 30.01.2015
18.05.2015 11:08:27
Цитата
Серж пишет: при обращении к таблице из другого потока текущая операция будет приостановлена до окончания обновления таблицы?
local t = {}
function OnAllTrade(alltrade)
table.sinsert(t, alltrade)
end
function main()
local t1 = t[1]
end
Будет ли потокобезопасной данная операция?
Надо делать так, как надо. А как не надо - делать не надо.
Michael Bulychev
Гость
18.05.2015 12:05:12
Возможно насчет глобальных я не совсем корректно выразился. Выполнение функции sinsert заблокирует выполнение кода в другом потоке до окончания работы функции.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
18.05.2015 12:25:32
Цитата
Michael Bulychev пишет: Выполнение функции sinsert заблокирует выполнение кода в другом потоке до окончания работы функции.
Давайте, чтобы не было разночтения сформулируем более точно. Выполнение функции sinsert заблокирует выполнение кода в другом потоке до окончания работы функции в любом случае или только при обращении из другого потока к таблице, модифицируемой sinsert? Другими словами, sinsert приостанавливает выполнение другого потока в любом случае или нет?
Надо делать так, как надо. А как не надо - делать не надо.
Понял. Спасибо. Вы не думаете, что об этом стоило упомянуть в документации?
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 23.01.2015
18.05.2015 14:20:21
Цитата
Серж пишет: Вы не думаете, что об этом стоило упомянуть в документации?
Здравствуйте, Мы рассмотрим этот вопрос
Пользователь
Сообщений: Регистрация: 30.01.2015
19.05.2015 18:15:22
хэш - это число. В луа используется для хранения строковых данных. В луа таким образом обеспечивается быстрое сравнение строк, так как сравниваются фактически числа. Кроме того, хранятся лишь уникальные строки, что исключает избыточное хранение копий строк.
Можете изменить алгоритм таким образом, чтобы параллельный поток блокировался только в том случае, если происходит попытка одновременного доступа к модифицируемой таблице?
Надо делать так, как надо. А как не надо - делать не надо.
Michael Bulychev
Гость
28.05.2015 05:01:15
Нет, не можем и не будем этого делать. За доступом к конкретной таблице пользователь должен следить сам.
Пользователь
Сообщений: Регистрация: 01.02.2015
28.05.2015 05:11:59
я так понимаю ввиду того, что может возникнуть взаимоблокировка?
Michael Bulychev
Гость
28.05.2015 05:17:32
Нет, просто нет такого механизма в Lua. за конкретным объектом должен следить сам пользователь.
Я про существующие средства в языке для многопоточной работы.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
10.06.2015 16:09:13
С колбеками, вроде, понятно: если в колбеке одного скрипта вызывается потокобезопасная функция, то работа основного потока QUIK и дополнительного main этого скрипта "замораживается" на время выполнения функции. А если потокобезопасная функция вызывается в main, окажет ли это влияние на потоки других скриптов?
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 01.02.2015
10.06.2015 16:32:35
Любое обращение к глобальным переменным, равно как и любая модификация стека в LUA происходит через критические секции. Исследования показывают, что нет в целом ряде случаев абсолютно никакой выгоды от многопоточности, если не используется соответствующая операционная система и многоядерные процессоры. Широко распространено и подтверждено на практике мнение, что число потоков - должно соответствовать числу ядер. Вот, кстати, статейка на тему:
Пользователь
Сообщений: Регистрация: 02.02.2015
миру мир!
10.06.2015 22:35:13
Цитата
Michael Bulychev пишет: Выполнение функции sinsert заблокирует выполнение кода в другом потоке до окончания работы функции.
Вообще любого Луа-кода, или заблокирует выполнение только другой потоко-безопасной функции работы с таблицами?
Иначе говоря, рассмотрим приведённый ранее пример:
Код
local t = {}
function OnAllTrade(alltrade)
table.sinsert(t, alltrade)
end
function main()
local t1 = t[1]
end
Предположим, что уже начался выполняться оператор
Код
local t1 = t[1]
из main()
И тут вызывается
Код
table.sinsert(t, alltrade)
из OnAllTrade(alltrade)
Это вполне возможно, т.к. это независимые потоки. Вопрос: table.sinsert() будет ждать завершение выполнения t1 = t[1] или нет?
Michael Bulychev
Гость
11.06.2015 03:58:26
Добрый день. Это нельзя сказать точно, тут, как говорится кто первый встал... Важен другой момент - при обычном insert возможна ситуация когда элемент t[1] уже существует, но еще ничем не заполнен. То есть isert это функция в процессе выполнения которой блокировка может случаться и освобождаться неоднократно. При использовании sinsert такого не случится - если элемент t[1] существует (t[1] ~= nil), то и его содержимое уже корректно заполнено.
Michael Bulychev
Гость
11.06.2015 04:01:56
Цитата
Старатель пишет: С колбеками, вроде, понятно: если в колбеке одного скрипта вызывается потокобезопасная функция, то работа основного потока QUIK и дополнительного main этого скрипта "замораживается" на время выполнения функции. А если потокобезопасная функция вызывается в main, окажет ли это влияние на потоки других скриптов?
Но пока выполняется потокобезопасная функция основной поток терминала "заморожен", информация с сервера не поступает, колбеки не вызываются. Это вы называете "никак не влияет"?
Надо делать так, как надо. А как не надо - делать не надо.
Michael Bulychev
Гость
11.06.2015 10:46:06
Он и так "заморожен" при выполнении колбека.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
11.06.2015 10:58:42
Michael Bulychev, мне кажется или вы потеряли основную мысль обсуждения?
Цитата
Старатель пишет: С колбеками, вроде, понятно: если в колбеке одного скрипта вызывается потокобезопасная функция, то работа основного потока QUIK и дополнительного main этого скрипта "замораживается" на время выполнения функции. А если потокобезопасная функция вызывается в main, окажет ли это влияние на потоки других скриптов?
Надо делать так, как надо. А как не надо - делать не надо.
Michael Bulychev
Гость
11.06.2015 11:01:09
Возможно. Давайте на примерах разбираться.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
11.06.2015 11:16:31
У меня такое ощущение, что это я вам рассказываю, как работает ваш программный продукт. Хотя наоборот было бы гораздо эффективней.
Скрипт 1:
Скрытый текст
Код
local bRun, sTime = true
local sClassCode, sSecCode = "QJSIM", "SBER"
function main()
while bRun do
PrintDbgStr("main1")
sleep(1000)
end
end
function OnStop()
bRun = nil return 0
end
function OnParam(class_code, sec_code)
if not bRun then return end
if sec_code ~= sSecCode or class_code ~= sClassCode then return end
local Time = getParamEx(class_code, sec_code, 'TIME').param_image
if Time ~= sTime then
PrintDbgStr("1: "..Time)
sTime = Time
end
end
Скрипт 2:
Скрытый текст
Код
local bRun, sTime
local sClassCode, sSecCode = "QJSIM", "SBER"
function main()
local t, n = {}, 5000000
for i = 1, n do t[i] = n - i end
PrintDbgStr("start")
bRun = true
table.ssort(t)
PrintDbgStr("end")
while bRun do sleep(100) end
end
function OnStop()
bRun = nil return 0
end
function OnParam(class_code, sec_code)
if not bRun then return end
if sec_code ~= sSecCode or class_code ~= sClassCode then return end
local Time = getParamEx(class_code, sec_code, 'TIME').param_image
if Time ~= sTime then
PrintDbgStr("2: "..Time)
sTime = Time
end
end
Запускаем - делаем выводы.
Надо делать так, как надо. А как не надо - делать не надо.
Michael Bulychev
Гость
11.06.2015 11:21:56
Похожего эффекта можно достичь и другими способами, этого мы и не скрывали никогда.
Michael Bulychev пишет: Похожего эффекта можно достичь и другими способами
Какими? (Речь сейчас не идёт про длительную обработку колбека.)
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 01.02.2015
11.06.2015 11:31:58
замените в скрипте №1 в майне sleep на равносильную задержку в виде цикла.
Michael Bulychev
Гость
11.06.2015 11:37:06
Цитата
Старатель пишет: Какими? (Речь сейчас не идёт про длительную обработку колбека.)
Для чего мы завели такие функции и чего они позволяют избежать я уже объяснял. В Вашем примере использование ssort совершенно не к месту. Используйте просто sort.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
11.06.2015 11:38:07
Цитата
sam063rus пишет: замените в скрипте №1 в майне sleep на равносильную задержку в виде цикла.
Пустого цикла? И? Терминал продолжает получать информацию с сервера, колбеки вызываются.
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
11.06.2015 11:41:36
Цитата
Michael Bulychev пишет: Для чего мы завели такие функции и чего они позволяют избежать я уже объяснял. В Вашем примере использование ssort совершенно не к месту. Используйте просто sort.
Вы, наверное, не поняли: это псевдокод. Таким образом, я показал вам, что утверждение
не верно. Это говорит о том, что использование потокобезопасных функций оказывает влияние на все запущенные скрипты.
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
11.06.2015 11:42:35
Цитата
Старатель пишет: Это говорит о том, что использование потокобезопасных функций оказывает влияние на все запущенные скрипты.
Независимо от потока, в котором они были вызваны.
Надо делать так, как надо. А как не надо - делать не надо.
Michael Bulychev
Гость
11.06.2015 11:51:04
Согласитесь, что пример немного не жизненный?
Пользователь
Сообщений: Регистрация: 01.02.2015
11.06.2015 11:59:35
, Прошу Вас, самым детальнейшим образом расписать, как устроено межскриптовое взаимодействие/влияние в QLUA -> интересует: 1. порядок инициализации главной виртуальной машины - > что после чего запускается, как и на каком этапе происходит цикл регистрации и опроса коллбеков. 2. Также прошу расписать в каких случаях создаётся новый lua-thread (имеется ввиду только в обычных скриптах. 3. (несовсем по теме, конечно, но... ) 1. в какое место совать свою GUI-билиотеку? в основное тело скрипта, 2. в майн 3. или создавать для этого новый поток ОС и делать в нём свою message-loop бо как диспетчеризация сообщений квиковским главным потоком уже будет не досягаема?
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
11.06.2015 12:04:52
Цитата
Michael Bulychev пишет: Согласитесь, что пример немного не жизненный?
Я что-то не понял, с чем вы спорите? Вы можете привести "жизненный пример", когда использование потокобезопасной функции в одном скрипте "никак не влияет" на другие скрипты?
Надо делать так, как надо. А как не надо - делать не надо.
Michael Bulychev
Гость
11.06.2015 12:08:16
Я не спорю, наоборот соглашаюсь. Про это поведение мы уже рассказывали.
Пользователь
Сообщений: Регистрация: 01.02.2015
11.06.2015 12:28:50
ну вот, опять убежал...
Пользователь
Сообщений: Регистрация: 30.01.2015
11.06.2015 14:21:54
Цитата
Michael Bulychev пишет: Нет, просто нет такого механизма в Lua. за конкретным объектом должен следить сам пользователь.
Но в луа нет ни функций QLUA, ни возможности создания функции main в отдельном потоке. - Это все сугубо ноу-хау QUIK. Может быть,продолжая развитие данного направления, сделать необходимые механизмы синхронизации потоков для всех пользователей? Я для себя кое-что сделал. Но некоторые вопросы удобнее решить на стороне терминала .
Пользователь
Сообщений: Регистрация: 01.02.2015
11.06.2015 15:36:10
честно сказать, я уже и на майн и на потоки согласен НО! Дайте примеры достойные подражания? А то - документация - никакая, техподдержка, если почитать их сообщения со старого и этого форума и сопоставить (благо MySQL сейчас может пользоваться каждый) друг другу - противоречит, разработчики - привыкли ограничиваться лишь парой фраз. В итоге, как говорится, "вот вам qlua и (ну вы поняли...)". При этом, сотрудники компании ещё сильно обижаются, когда их упрекают в отсутствии знания собственного продукта. Видать, писать, что "проблема будет исправлена в следующей версии" в этой компании уже давно вошло в привычку за 15 лет.
Пользователь
Сообщений: Регистрация: 01.02.2015
11.06.2015 15:52:04
хочу привести реальный пример, из жизни. хоть он и несовсем по теме - но главное - суть: есть 3D-движок CryEngine - от вполне себе современной и раскрученной игры. Причём, он тоже поддерживает LUA. Так вот: чуть покопавшись в его SDK и примерах скриптинга - я чот не нашёл там ни повального использования метатаблиц, ни корутин, ни потоков. Там есть развитая библиотека уже встроенных на уровне движка объектов (Entity). Чтобы наследовать какой-то объект или свойство от другого объекта - там не надо писать полушаманский код на метатаблицах - всё сделано на уровне домохозяек и школьников - хочешь наследовать - вызови пару функций и будет тебе счастье. Насчёт доступа ке глобальным переменным, во многих скриптовых движках - уже давно для этого используют классы, т.е. глобальная переменная - это - тоже класс, причём встроенный в сам движок. Пользователь - вообще в данном случае не думает ни о каких потоках и синхронизации - он просто дёргает методы и навешивает на эту глобальную переменную - события. Список можно бесконечно продолжать. Хочется ещё раз спросить: для кого эта QLUA - затевалась? Кто целевая аудитория? Какие перспективы? Если всё - это для трейдеров - то это точно не для них, потому как разгребать за вами ваши же огрехи ценою своего счёта по причинам описанным выше - не хватит денег ни у кого. Если это для программистов - то программисты от него тоже - не в восторге. Им было бы куда проще и гибче писать на C++ и не быть ни в чём стеснёнными. Я не спорю, что сама по себе LUA - вполне себе достойный скриптовый язык. НО!!! Вы доведите её уже наконец, до ума, а не выпускайте на рынок вечно-сырой продукт.
Пользователь
Сообщений: Регистрация: 31.01.2015
26.06.2015 22:23:02
Уважаемые разработчики, ответьте на такой вопрос: Является ли запись в файл значений того или иного набора переменных с помощью функции file:write() потокобезопасной? Иными словами, если в один и тот же файл будет производиться запись в коллбэках (типа OnParam, OnTrade, OnQuote и т.п.), а также в функции main(), то не приведет ли это к каким-то нежелательным или непредсказуемым последствиям?
Пользователь
Сообщений: Регистрация: 23.01.2015
30.06.2015 10:07:44
Цитата
Дмитрий пишет: Уважаемые разработчики, ответьте на такой вопрос: Является ли запись в файл значений того или иного набора переменных с помощью функции file:write() потокобезопасной? Иными словами, если в один и тот же файл будет производиться запись в коллбэках (типа OnParam, OnTrade, OnQuote и т.п.), а также в функции main(), то не приведет ли это к каким-то нежелательным или непредсказуемым последствиям?
write не является нашей функцией, это стандартная функция Lua, поэтому, затруднимся дать однозначный ответ. Попробуйте поискать ответ в сообществе Lua