|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Прочитал у Альбахари , что это обычно приватный объект: авторThe synchronizing object is typically private (because this helps to encapsulate the locking logic) Т. е. он разбирает какой-то конкретный случай, когда логика работы с многопоточными данными вся в одном классе инкапсулирована. А что, если мне эти данные надо давать использовать многим другим классам - т. е. сделать их публичными? Например, у меня схема такая: класс, который что-то делает (считает, например) - расчётный класс Calc; класс, который хранит результаты и выводит их на экран: Код: c# 1. 2. 3. 4.
Свойство ResultValues должно иметь многопоточный доступ - Calc постоянно пишет в это свойство, а Result постоянно читает из него и показывает результаты. Проблема в том, что ResultValues - постоянно обновляет свои данные по мере расчёта. При этом по мере расчёта надо показывать промежуточные результаты. Т. е. нужно как-то синхронизировать ResultValues между классами Calc и Result. А поскольку ResultValues это публичное свойство, то мне приходится придумывать некий синхронизирующий объект, который надо шарить между этими двумя классами. Я делаю это так - создаю класс приложения, в который помещаю объекты Calc, Results и синхронизирующий объект. Таким образом я могу расшарить один и тот же синхронизирующий объект между Calc и Result - передавать его через конструкторы этих классов или прямо в те их методы, который используют свойство ResultValues. Т. е. моя схема отличается от того, что говорит Альбахари, что логика синхронизации должна быть инкапсулирована в одном классе. Я делаю всё правильно, или можно придумать схему лучше для моего случая? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 07:19 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
А что, если сделать само свойство ResultValues синхронизируемым объектом, и везде, где используется это свойство - неважно, в своём классе, в котором объявлено это свойство, или в чужих - писать lock(ResultValues)? Был ещё вариант, сделать это свойство приватным, но добавить публинчые обёртки над этим свойством, типа GetResultValues, AddNewValuesToResult и т. п., которые бы под локом делали бы свою работу. Но показалось, что это слишком мудрёный вариант, который мало что даёт. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 07:22 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser987А что, если сделать само свойство ResultValues синхронизируемым объектом, и везде, где используется это свойство - неважно, в своём классе, в котором объявлено это свойство, или в чужих - писать lock(ResultValues)? Был ещё вариант, сделать это свойство приватным, но добавить публинчые обёртки над этим свойством, типа GetResultValues, AddNewValuesToResult и т. п., которые бы под локом делали бы свою работу. Но показалось, что это слишком мудрёный вариант, который мало что даёт. Первый вариант плох тем, что невозможно заставить или как-то сообщить пользователю класса Result, что с ResultValues надо работать именно так. А второй хорош тем, что я заставляю пользователя ResultValues работать с ним только через методы, которые уже внутри используют блокировку. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 07:24 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Возьми ConcurrentBag это тот же лист, только потокобезопасный. Хотя тут очередь больше подойдет ConcurrentQueue Все потокобезопасные классы ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 07:27 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Dima TВозьми ConcurrentBag это тот же лист, только потокобезопасный. Хотя тут очередь больше подойдет ConcurrentQueue Все потокобезопасные классы Мне кажется, что потокобезопасные классы тут не очень подходят. Я уточню желательный сценарий использования ResultValues: 1) расчёт у меня работает циклически - приходит новая порция данных и класс Calc делает итерацию расчёта; 2) при каждой итерации класс Calc полностью обновляет ResultValues; 3) после каждой итерации класс Result считывает "снимок" ResultValues и выводит его на экран. Если не получается после каждой итерации считать, можно пропускать - главное, чтобы Result не считывал значения из ResultValues посередение заполнения ResultValues классом Calc. В реальности я это реализую так - класс Calc молотит в бесконечном цикле while(true), ожидая новых данных и делая паузы посредством Thread.Sleep (думаю в будущем заменить на какой-нибудь SpinLock или Wait/Pulse, но пока так), класс Result делает то же самое - while(true) и Thread.Sleep. И оба класс работают с ResultValues через расшаренный синхронизирующий объект с помощью lock(synchObject). ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 07:57 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Т. е. из-за вот этого AlexUser9872) при каждой итерации класс Calc полностью обновляет ResultValues; 3) после каждой итерации класс Result считывает "снимок" ResultValues я не вижу смысла в потокобезопасных коллекциях в моём случае. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 07:58 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser987В реальности я это реализую так - класс Calc молотит в бесконечном цикле while(true), ожидая новых данных и делая паузы посредством Thread.Sleep (думаю в будущем заменить на какой-нибудь SpinLock или Wait/Pulse, но пока так), класс Result делает то же самое - while(true) и Thread.Sleep. И оба класс работают с ResultValues через расшаренный синхронизирующий объект с помощью lock(synchObject). Да, забыл уточнить, что, естественно, каждый из классов Calc и Result работает в своём потоке. Точнее, в отдельных потоках запускаются методы этих классов, ответственные, соответственно, за расчёт и за вывод результатов. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 08:01 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser9872) при каждой итерации класс Calc полностью обновляет ResultValues; ... главное, чтобы Result не считывал значения из ResultValues посередение заполнения ResultValues классом Calc. Тогда генери в Calc новый List и присваивай по окончанию, т.е. так Код: c# 1. 2. 3. 4. 5.
И не надо никаких синхронизаций. Можешь AutoResetEvent добавить для пробуждения Result ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 08:26 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Dima TИ не надо никаких синхронизаций. Можешь AutoResetEvent добавить для пробуждения Result Почему не надо? А если класс Result перебирает элементы ResultValues, а в этом время класс Calc обновляет/подменяет ResultValues? Т. е. в моём случае он обновляет данные в ResultValues, а в вашем - подменяет всю коллекцию новым объектом ResultValues. Но результат всё равно один - изменение коллекции ResultValues во время её перебора другим потоком. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 08:30 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Я ещё думал создать для ResultValues коллекцию List<List<double>> ResultValuesList И чтобы после каждого расчёта Calc добавлял в ResultValuesList результаты, а Result бы забирал только последний на текущий момент элемент - т. е. последний результат. Ну и после каждого такого забора удаление из ResultValuesList всех предыдущих коллекций результатов, чтобы память не занимали. Как такой вариант? Тогда точно синхронизаций и блокировок не понадобится. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 08:34 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser987Dima TИ не надо никаких синхронизаций. Можешь AutoResetEvent добавить для пробуждения Result Почему не надо? А если класс Result перебирает элементы ResultValues, а в этом время класс Calc обновляет/подменяет ResultValues? Т. е. в моём случае он обновляет данные в ResultValues, а в вашем - подменяет всю коллекцию новым объектом ResultValues. Но результат всё равно один - изменение коллекции ResultValues во время её перебора другим потоком. Результаты разные: в твоем случае объект один, в моем случае два разных, поэтому синхронизация не нужна. Немного не дописал, чтобы в Result не сглючило лучше так Код: c# 1. 2. 3. 4.
Т.е. Calc() создал объект, наполнил, сохранил ссылку на объект в ResultValues и больше с объектом не работает. Result() взял ссылку из ResultValues и вывел. Точка пересечения Calc() и Result() только в передаче ссылки через ResultValues. Эта операция атомарная, т.е. не требует доп.синхронизаций (если путаю поправьте). ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 08:43 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser987В реальности я это реализую так - класс Calc молотит в бесконечном цикле while(true), ожидая новых данных и делая паузы посредством Thread.Sleep Черезжопная реализация. Sleep() - вставка тормоза чтоб проц в холостую не гонять. Разбирайся с источником данных, чтобы он будил Calc при появлении данных. AlexUser987(думаю в будущем заменить на какой-нибудь SpinLock или Wait/Pulse, но пока так), класс Result делает то же самое - while(true) и Thread.Sleep. И оба класс работают с ResultValues через расшаренный синхронизирующий объект с помощью lock(synchObject). Используй AutoResetEvent: Result висит на эвенте, Calc как посчитал и сохранил сбрасывает эвент, Result просыпается, выводит и дальше висит на эвенте. PS Почитай Дж. Рихтер CLR via C# . Часть V. Многопоточность. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 08:46 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Dima TAlexUser987пропущено... Почему не надо? А если класс Result перебирает элементы ResultValues, а в этом время класс Calc обновляет/подменяет ResultValues? Т. е. в моём случае он обновляет данные в ResultValues, а в вашем - подменяет всю коллекцию новым объектом ResultValues. Но результат всё равно один - изменение коллекции ResultValues во время её перебора другим потоком. Результаты разные: в твоем случае объект один, в моем случае два разных, поэтому синхронизация не нужна. Немного не дописал, чтобы в Result не сглючило лучше так Код: c# 1. 2. 3. 4.
Т.е. Calc() создал объект, наполнил, сохранил ссылку на объект в ResultValues и больше с объектом не работает. Result() взял ссылку из ResultValues и вывел. Точка пересечения Calc() и Result() только в передаче ссылки через ResultValues. Эта операция атомарная, т.е. не требует доп.синхронизаций (если путаю поправьте). Да, вы правы - я упустил из виду var list = new List<double>(); в классе Calc. Спасибо и за другие советы - посмотрю. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 13:29 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser987var list = new List<double>(); ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 13:30 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Не вчитывался особо в суть проблемы,уверен, что задачу можно решить проще и по другому, но ответы на вопросы на всякий случай. AlexUser987А что, если сделать само свойство ResultValues синхронизируемым объектом, и везде, где используется это свойство - неважно, в своём классе, в котором объявлено это свойство, или в чужих - писать lock(ResultValues)? SyncRoot . Как раз тот же принцип. Все уже придумано до нас. AlexUser987Был ещё вариант, сделать это свойство приватным, но добавить публинчые обёртки над этим свойством, типа GetResultValues, AddNewValuesToResult и т. п Делается обычно так. В класс добавляются 2 метода. Например, Lock и UnLock. В Lock добавляем Monitor.Enter, в UnLock сами догадаетесь? Применение: Код: plaintext 1. 2. 3. 4. 5. 6.
Но ценность таких вариантов достаточно сомнительна. В первую очередь нужно смотреть на возможность lock-free работы. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 14:21 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Arm79Не вчитывался особо в суть проблемы,уверен, что задачу можно решить проще и по другому, но ответы на вопросы на всякий случай. AlexUser987А что, если сделать само свойство ResultValues синхронизируемым объектом, и везде, где используется это свойство - неважно, в своём классе, в котором объявлено это свойство, или в чужих - писать lock(ResultValues)? SyncRoot . Как раз тот же принцип. Все уже придумано до нас. AlexUser987Был ещё вариант, сделать это свойство приватным, но добавить публинчые обёртки над этим свойством, типа GetResultValues, AddNewValuesToResult и т. п Делается обычно так. В класс добавляются 2 метода. Например, Lock и UnLock. В Lock добавляем Monitor.Enter, в UnLock сами догадаетесь? Применение: Код: plaintext 1. 2. 3. 4. 5. 6.
Но ценность таких вариантов достаточно сомнительна. В первую очередь нужно смотреть на возможность lock-free работы. Про синк рут спасибо. Про дальнейшее - что-то сомнительным выглядит. Как заставить пользователя класса пользоваться моим классом именно по такой сложной схеме? С таким же успехом можно заставить его самостоятельно локать свойства-коллекции этого класса - т. е. никак. Разве что в комментариях или документации к классу очень сильно попросить, что делать надо именно так, а не иначе, а если нет, то будет упс. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 15:55 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Про синк рут полезная вещь. Просто на самом деле я упростил свой пример и у меня по смыслу не одна коллекция пишется-читается, а несколько, поэтому выделить специальный объект под синхронизацию ВСЕГО этого дела в виде "атомарной" операции под локом кажется более подходящим. А вообще, как поступить, если в моём классе Result не просто одна коллекция, которую постоянно целиком обновляет другой класс, а нечто смешанное? Например, у меня вот такая коллеция, как выше описана - т. е. полностью обновляющаяся в каждой итерации расчёта. Потом ещё другая коллеция, которая лишь добавляет очередную пачку рассчитанных данных в конец уже существующих - т. е. пополняющиеся результаты. Плюс ещё просто числа, которые обновляются. И вот весь этот набор надо бы защищить от изменения классом расчёта Calc, пока его класс результатов Result выводит на экран. Тут удобнее всё это под одним общим локом разместить, или как? Или к каждому типу данных свой подход - где-то volatile, где-то из concurrent collection взять, а где-то через lock сделать? Я вот пока реализовал - всё изменения и чтения всех этих разношёрстных результатов поместил под одним общим lock. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 16:02 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser987Я вот пока реализовал - всё изменения и чтения всех этих разношёрстных результатов поместил под одним общим lock. Работает? Проблем по скорости нет? Никто не жалуется? Значит, нормально. Сделайте хоть как то, чтобы работало, потом рефакторьте код. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 17:08 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Arm79AlexUser987Я вот пока реализовал - всё изменения и чтения всех этих разношёрстных результатов поместил под одним общим lock. Работает? Проблем по скорости нет? Никто не жалуется? Значит, нормально. Сделайте хоть как то, чтобы работало, потом рефакторьте код. Да давно уже работает. Я вот откопал своё старьё и думаю, как получше сделать. Т. к. скоро что-то подобное придётся снова делать - думаю, не повторять же то же самое. Может, получше варианты есть. Так сказать, общие подходы. Тот же Альбахари про это, вроде, ничего не пишет. В этом вашем Рихтере есть что подобное? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 17:27 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Dima TТочка пересечения Calc() и Result() только в передаче ссылки через ResultValues. Эта операция атомарная, т.е. не требует доп.синхронизаций (если путаю поправьте). ставьте volatile и должно быть норм. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 18:03 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser987В этом вашем Рихтере есть что подобное? Почитай, хуже не будет. ХЗ есть или нет, слишком уж абстрактно у тебя задача сформулирована. По крайней мере узнаешь о всех возможных альтернативах решения твоей задачи. Как выше упомянули надо в сторону lock-free идти (в моих примерах оно самое). Закон Амдала никто не отменял, поэтому чем больше синхронизируешься, тем меньше пользы от распараллеливания. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 18:04 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser987, А каждая порция данных от Calc должна быть обработана Result? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 18:08 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Arm79AlexUser987, А каждая порция данных от Calc должна быть обработана Result? Нет. Result делает слепок с набора результатов и потом сразу "освобождает" (в смысле, что перестаёт использовать - считывать значения там и прочее) этот набор, чтобы Calc дальше мог в него писать. В момент создания слепка я и применяю блокировку через lock. После создания слепка Result неспешно выводит результаты из этого слепка на экран. Неспешно в том смысле, что копирование данных в слепок происходит гораздо быстрее, чем отображение на экране. В этом время Calc под локом пишет в набор результатов, которые только что освободил Result. Обычно у меня получается, что Calc может множество итераций расчёта провести на одну итерацию вывода результатов - т. е. он несколько раз перезапишет набор результатов. Поэтому Result берёт слепок всегда с последней версии результатов. Это нужно, чтобы результаты отображались в реальном времени - с приемлемой задержкой по отношению к поступающим данным. Задачи показать вывод именно по всем результатам у меня пока нет. Если будет - переделаю, чтобы результаты накапливались в коллекции. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 18:45 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Dima T Закон Амдала Кстати, он показывает, что технологической сингулярности не будет. Даже если доведут до ума квантовые компьютеры. Но будет некоторое приближение к ней. Довольно близкое и болезненное. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 18:48 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser987, Элементов в наборе данных много? десятки? сотни? тысячи? миллионы? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 18:57 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser987Result делает слепок с набора результатов и потом сразу "освобождает" (в смысле, что перестаёт использовать - считывать значения там и прочее) этот набор, чтобы Calc дальше мог в него писать. В момент создания слепка я и применяю блокировку через lock. ИМХУ тут обратно надо. Calc делает слепок и отдает его, тогда блокировок не надо. Опять же вопрос как часто это надо? Например если Result() обрабатывает только каждый тысячный слепок, то будет лишний тормоз. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 19:22 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Dima TИМХУ тут обратно надо. Calc делает слепок и отдает его, тогда блокировок не надо. Т. е. тот, кто считает, тот же и слепок делает? Да в принципе не важно, по-моему, кто там чего делает - Calc, Result или ещё какие сущности. Я просто примерно раскидал задачи по классам. Можно всё и в один класс запихать, а можно и ещё разделить. Или я вас не понял. Важно, что есть одновременный доступ к результатам расчёта из разных потоков. Потому что вот эти вещи 1) расчёт, 2) сохранение результатов в переменных в ОЗУ в процессе расчёта, 3) создание слепка из результатов, 4) вывод слепка результатов на экран должны быть как можно больше независимы друг от друга. У меня раньше было без слепка. Т. е. на протяжении всего расчёта данные писались в набор результатов под локом, и класс Result не мог получить к ним доступ, чтобы вывести результаты на экран. Когда же получал, то выводил именно результаты (пункт 2), а не слепок. Расчёт длится гораздо дольше создания слепка результатов. Поэтому, когда я ввёл слепок, я смог больше распараллелить всю работу, т. к. теперь, фактически, локи работали только в моменты создания слепка. Вообще без локов, на мой взгляд - только если накапливать весь набор результатов в коллекцию наборов результатов. И потом Result будет брать самый последний добавленный набор результатов (банально проверяем свойство Count без всяких локов, и берём текущее последнее значение). Ну, я уже об этом раньше писал. Я так думаю. Arm79AlexUser987, Элементов в наборе данных много? десятки? сотни? тысячи? миллионы? В смысле элементов? Число коллекций, объектов, значений? Или вплоть до числа элементов в каждой коллекции? Если первое, то 20-100. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 20:46 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser987В смысле элементов? Число коллекций, объектов, значений? Или вплоть до числа элементов в каждой коллекции? Если первое, то 20-100. Коллекций до 100? А в каждой коллекции сколько элементов? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2015, 23:42 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Arm79AlexUser987В смысле элементов? Число коллекций, объектов, значений? Или вплоть до числа элементов в каждой коллекции? Если первое, то 20-100. Коллекций до 100? А в каждой коллекции сколько элементов? Нет. Коллекций штук 10-20. Плюс несколько десятков строковых и числовых переменных, собранных в разные объекты. Коллекции есть разные. Есть, где в принципе 1-10 элементов и больше навряд ли будет. А есть, где 100-10000. Да и я сейчас стараюсь переработать, чтобы не более 2000-3000 было. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.12.2015, 07:32 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
AlexUser987Dima TИМХУ тут обратно надо. Calc делает слепок и отдает его, тогда блокировок не надо. Т. е. тот, кто считает, тот же и слепок делает? Да AlexUser987Да в принципе не важно, по-моему, кто там чего делает - Calc, Result или ещё какие сущности. Я просто примерно раскидал задачи по классам. Можно всё и в один класс запихать, а можно и ещё разделить. Или я вас не понял. Важно, что есть одновременный доступ к результатам расчёта из разных потоков. Потому что вот эти вещи 1) расчёт, 2) сохранение результатов в переменных в ОЗУ в процессе расчёта, 3) создание слепка из результатов, 4) вывод слепка результатов на экран должны быть как можно больше независимы друг от друга. Определись уже важно или нет. Если слепок делает Result то он должен остановить Calc, следовательно Calc должен регулярно проверять блокировку, что тоже ресурсы потребляет. Если слепок делает Calc, то ему не надо проверять блокировки, он просто сделал новый слепок, отдал на него ссылку и больше этот слепок не трогает. Чтобы отдать ссылку синхронизации не надо. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.12.2015, 08:33 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Dima TЕсли слепок делает Calc, то ему не надо проверять блокировки, он просто сделал новый слепок, отдал на него ссылку и больше этот слепок не трогает. Чтобы отдать ссылку синхронизации не надо. Да, не надо. Просто, по-вашему, Calc будет после каждой итерации расчёта слепки делать в том же потоке, вместо того, чтобы заниматься новой итерацией. Я вас правильно понял? У меня логика такая, что Result сам запрашивает/делает слепок. Т. е. Calc должен только молотить расчёт. В принципе, если Result не запросит ни разу результат для отображения, то Calc так и домолотит до конца и оставит в переменных результатов последний вариант результатов. Это я сделал для того, чтобы легко было приспособить всю схему под клиент-сервер. Когда сервер только считает, но не оповещает клиента, что закончилась очередная итерация расчёта. Вместо этого сам клиент запрашивает сервер в цикле и, если новая итерация закончилась, то получает слепок. При этом неважно, какой класс делает слепок на стороне сервера - сам Calc или специально созданный для этого класс. Вот это я имел ввиду, говоря авторДа в принципе не важно, по-моему, кто там чего делает - Calc, Result или ещё какие сущности А насчёт этого авторэти вещи 1) расчёт, 2) сохранение результатов в переменных в ОЗУ в процессе расчёта, (у меня объединено с 1) 3) создание слепка из результатов, 4) вывод слепка результатов на экран должны быть как можно больше независимы друг от друга. я имел ввиду по потокам. Т. е. вышеперечисленные пункты должны выполняться в разных потоках. Но при этом код этих пунктов может быть где угодно - хоть в одном классе, хоть в разных - это просто методы классов. И вот в клиент-серверном варианте я сделал как вы сказали - у меня метод, делающий слепок, находится в классе Calc (исторически сложилось - ещё не разбил свой god-class на части). Класс Result находится на клиенте. Да, в принципе, и в локальном варианте то же самое - просто библиотеку расчёта я перенёс из веб-сервиса на клиент и принцип работы не изменился - Result запрашивает Calc о новых результатов и просит сделать слепок. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.12.2015, 15:34 |
|
Насчёт синхронизируемого объекта - lock(synchObject)
|
|||
---|---|---|---|
#18+
Я, наверное, вас запутал. Потому что хотел задать простой вопрос, а реальная ситуация у меня сложнее. Пришлось наворачивать и наворачивать по мере обсуждения. Вобщем, я достаточно просветился, спасибо за помощь. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.12.2015, 15:35 |
|
|
start [/forum/topic.php?all=1&fid=20&tid=1400964]: |
0ms |
get settings: |
10ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
35ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
56ms |
get tp. blocked users: |
1ms |
others: | 14ms |
total: | 150ms |
0 / 0 |