![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| multikoder |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 3 Регистрация: 2.4.2014 Репутация: нет Всего: нет |
Почему то редко встречается такое сочетание.
Обычно пишут по отдельности или многопоточных или объектно-ориентированных. Какие принципы ООП нарушаются в многопоточных программах? Можно ли писать многопоточные программы полностью соответствующие ООП? |
|||
|
||||
| Cheloveck |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1578 Регистрация: 26.7.2008 Где: Тула Репутация: 3 Всего: 32 |
-------------------- ![]() |
|||
|
||||
| Romikgy |
|
|||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
грубо говоря поток это упрощенный вариант процесса , в процессах никто не запрещает ООП....
-------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
|||
|
||||
| multikoder |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 3 Регистрация: 2.4.2014 Репутация: нет Всего: нет |
Процессы это отдельные программы, которые ничего друг про друга не знают.
У потоков могут быть общие переменные, через которые они взаимодействуют. И это похоже на нарушение инкапсуляции. |
|||
|
||||
| Alexeis |
|
|||
![]() Амеба Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 12 Всего: 459 |
ООП и многопоточность как соленое и серое. Но с точки зрения С++ многопоточность усложняет написание ООП программ. Считается, что объект каждый момент времени находиться в некотором определенном состоянии, а переход объекта из одного состояния в другое осуществляется мгновенно путем отсылки ему сообщения. Состояние объекта, грубо говоря, это значение всех его полей. На практике на время вызова функции (обработка сообщения) объект находиться в некотором неопределенном состоянии (невозможно одновременно изменить состояние множества полей). Для однопоточной программы нахождение в неопределенном состоянии не проблема, поскольку пока функция не выполнилась до конца другая не может исполнятся. В многопоточной же программе объект может начать обработку сообщения (вызов функции) в тот момент когда он (объект) еще находится в неопределенном состоянии. Это и станет нарушением концепции ООП. Поэтому многопоточные ООП программы должны использовать мьютексы для того, чтобы исключить неопределенное состояние. Т.е. пока не будет произведен захват мьютекса нельзя будет менять состояние объекта.
-------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
| Cheloveck |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1578 Регистрация: 26.7.2008 Где: Тула Репутация: 3 Всего: 32 |
Alexeis, всё это верно для любой структуры данных, даже для массива. Так что ООП тут не при чём.
-------------------- ![]() |
|||
|
||||
| Alexeis |
|
|||
![]() Амеба Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 12 Всего: 459 |
Несмотря на то, что ООП и многопоточность с точки зрения теории это как серое и соленое. Т.е. понятия несвязанные, но тем не менее, на практике, в частности в реализации С++ многопоточность рушит типичный механизм изменения состояния объекта (невозможно записывать данные в поля напрямую). В тоже время как любая произвольно выбранная структура или массив не описывает состояние целиком, поэтому вообщем случае нельзя говорить о неопределенности состояния в случае простых структур данных. У меня, например, есть класс массива, который без блокировки может безопасно производить одновременно 2е операции записи в массив. Именно по той причине, что один массив это еще не состояние. Проблемы начинаются у тебя как у программиста, когда ты у себя в голове рассматриваешь массив как объект подобный объекту stl vector. Но на самом массив это лишь последовательность элементов объединенная одним именем. Я могу рассматривать любую последовательность элементов как некоторое состояние массива. В этом случае, массив в любой момент времени находиться в некотором определенном состоянии. Следовательно, любые операции с ним из любых потоков также будут корректно менять его состояние. -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
multikoder, они ортогональны, одно другому не мешает. темы сильно разные (разного уровня).
можно использовать совместно, можно раздельно, можно вообще не использовать)))) Alexeis, ООП и многопоточность не противопоставлены друг другу, не надо выдумывать про практику. многопоточность изменяет подход к алгоритмизации в целом (независимо от использования ООП), требует обеспечения определенных условий, но и только. модель, в которой объект одновременно занимается двумя задачами, вполне реальна. есть и не связанные с многопоточностью условия, которые мы должны соблюдать (в т.ч. используя ООП), просто они настолько привычны, что их выполнение нам кажется обычным делом. распределение памяти, например. |
|||
|
||||
| Alexeis |
|
|||
![]() Амеба Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 12 Всего: 459 |
Меняет ли что-то многопоточность если задача решена при помощи чистых функций? Модель в которой объект занимается решением задач, а тем более 2х сразу, вообще не ООП модель. Задачи решают функции. Объект концептуально не решает задачи как таковые, он лишь реагирует на сообщения. Задача, процесс и т.д. это не про ООП. ООП - это сообщения, события (сигналы), состояния. Менеджер памяти Состояние №1 - 25Мб выделенной памяти, 47Мб резерва Поток №1 --> Сообщение №1 запрос 1Мб памяти. Поток №2 --> Сообщение №2 запрос 2Мб памяти. Состояние №2 - 26Мб выделенной памяти, 46Мб резерва Состояние №3 - 28Мб выделенной памяти, 44Мб резерва Хотя объект получил 2 сообщения одновременно, он все равно последовательно перешел сначала в состояние №2, затем в состояние №3 . Это совсем плохой пример, поскольку здесь параллельные потоки выполняются по очереди и еще медленнее чем это было бы в однопоточном режиме. И я совсем не говорил, что параллельное исполнение как-то противоречит ООП концепции. Оно противоречит реализации ООП в С++ . В языке С++ для реализации ООП принято, что состояние определяется набором переменных-членов класса. Посылка сообщения реализуется через вызов функции. Синтаксис С++ не имеет языковых конструкций позволяющих указать, что группа полей должна изменять свои значения одной атомарной операцией. Параллелизм С++ ООП реализуется не проще чем на языке С , т.е. отсутствует напрочь. Совсем другое дело Qt, где посылка сообщения заменяется сигналом. Если источник сигнала и слот находятся в разных потоках, то в одном из вариантов реализации сигнал формирует сообщение в очереди сообщений объекта и состояние объекта изменяется атомарно в тот момент, когда объект обработает сообщение. -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
| baldina |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
за семантику и согласованность операций класса с++ отвечает программист, и неважно, в одно- или многопоточной среде это реализуется. в с++ нет типичного механизма изменения состояния объекта, он должен быть разработан для конкретного класса.
поэтому говорить, что некий типичный механизм что-то там рушит - неверно. ООП это действительно объекты, имеющие состояние и обменивающиеся сообщениями. а раз в концепции нет "решения задач", то разговор о свойстве решения задач, в т.ч. многопоточности, не имеет смысла. алгоритмы и их реализация не пересекаются с ООП. многопоточность не влияет и на использование класса: работа с потоками и синхронизация скрыты внутри методов класса.
ок, реагирует на следующее сообщение, не закончив обрабатывать предыдущее. стало легче от такой формулировки? вот модель. представим объект, решающий систему уравнений. метод solve() меняет состояние объекта: после изменения состояния система решена. такое изменение состояния занимает значительное время. также объект умеет реагировать на сообщение estimate_time(), в качестве реакции на которое он должен вернуть значение времени, через которое система будет решена.
да это и не нужно, многопоточность - не часть языка, а часть стандартной библиотеки. GC тоже нет, неаккуратные указатели могут порушить программу, но никому не приходит в голову говорить, что использование динамической памяти плохо согласуется с ООП. Добавлено через 5 минут и 48 секунд
Это совсем плохой пример, поскольку представляет объект как state machine. Это слишком узко. Объект это обобщение SM, а не наоборот. Реальные объекты настолько сложны, что говорить о перечне состояний не приходится. Вместо этого оперируют инвариантами. |
||||||
|
|||||||
| Lukkoye |
|
||||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 86 Регистрация: 23.3.2013 Репутация: 1 Всего: 1 |
Плюсы - язык, расширяемый за счет собственных библиотек. То бишь отсутствие "синтаксического сахара" от компилятора не означает, что на плюсах нельзя пилить атомарные операции. В частности см: Стандартная поддержка атомарных операций: http://en.cppreference.com/w/cpp/atomic/atomic Стандартные средства для поддержки многопоточного программирования: http://en.cppreference.com/w/cpp/thread/unique_lock http://en.cppreference.com/w/cpp/thread/mutex Вообще, очень много всяких инструментов для самых разных ситуаций. Перечислять можно долго, проще просто полистать сайт-документацию.
Неправда. Стандартные средства многопоточного программирования предлагают использовать технологию raii Например, вот так можно обеспечить "простой потока" пока не другой поток не завершит какую то свою работу:
Поток пробудил ото сна другой поток, который выполнил:
Это лишь краткий пример автоматики, которая возможно благодаря raii, который возможен благодаря ООП. На pure С сделать что-то подобное невозможно. Qt умеет это так же за счет библиотек языка, а не за счет ядра языка с++, на котором он базируется. Кютешечный мьютекс, или стандартный мьютекс - это всего лишь деталь библиотеки. Это сообщение отредактировал(а) Lukkoye - 2.4.2014, 22:37 |
||||||
|
|||||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
на С все возможно, только многословнее. raii особенно удобен в среде с исключениями, но в С нет исключений, и в этом смысле проблем меньше. raii часто ошибочно связывают с ООП, но фактически к ООП он не относится. просто некоторые средства некоторых языков с поддержкой ООП позволяют это изящно реализовать. |
|||
|
||||
| Alexeis |
|
||||||||||||||
![]() Амеба Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 12 Всего: 459 |
Не согласен. Каждый ЯП имеет свой набор синтаксических конструкций предназначенных для выполнения определенного круга задач. Возьмем к примеру язык С и реализуем на нем наследование.
Объект B унаследовал все из объекта А, и дополнил его новым полем b; Теперь возьмем язык С++ .
С точки зрения концепции ООП оба способа реализуют наследование, однако язык С++ указывает нам на то что наследование следует реализовывать именно 2м способом, а не первым. Теперь подумаем как можно сохранить состояние объекта. Инкапсуляция. Можно это сделать так.
А можно сделать это так.
И тот и другой способ хранит состояние внутри объекта. Но в одном случае это некоторый набор байтов, который можно испортить неправильным кодом. Во втором случае состояние хранит вложенный объект, доступ к которому ограничивается специальным средством языка - модификатором protected . Модификатор protected/private - это типичный способ реализации инкапсуляции состояния объекта в С++ . Его использование подразумевает то, что поля будут описываться следом за ним. Он защищает поля от посягательства других объектов. Использование 1го варианта кода допустимо с точки зрения С++, но не типично для этого ЯП. И 3я ситуация. Многопоточное ООП.
Сохраняется ли правильное состояние объекта А при любых операциях? Да! Защищает ли хоть как-то средство С++ состояние объекта А от одновременно полученных сообщений? Нет! С точки зрения потокозащищенности состояния объекта данный код ничем не безопаснее чем.
Т.е. если я захочу в иной функции написать *a->wndsize = *r; я это сделаю с одинаковым успехом, что в варианте кода С++, что в варианте С . И в обоих случаях у меня появилось лишнее поле mtx_wndsize, которое никак не определяет состояние объекта. В С++ есть средства для реализации только однопоточного ООП. Я бы хотел видеть 2й вариант реализации многопоточного ООП на подобии такого :
Все поля объекта хранят исключительно состояние объекта. Правильность состояния объекта гарантируют средства языка. Это сообщение отредактировал(а) Alexeis - 3.4.2014, 17:09 -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
||||||||||||||
|
|||||||||||||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
Alexeis, букв много но ни слова про "типичный способ изменения состояния объекта" (понятно почему - его просто нет. можно с этим не соглашаться, но тогда плиз ссылку на конструкцию, стандарт или хотя бы best practices от известного специалиста)
у меня есть класс, скажем потокобезопасная реализация std::vector. как пользователь класса я не должен думать о многопоточности. как разработчик класса я должен об этом думать, обеспечивая согласованное состояние класса. как это сделать, зависит от назначения класса и гарантий потокобезопасности, которые планируется реализовать, но вся реализация будет скрыта от пользователя. многопоточное ООП это что-то новое)))) правда существует концепция актеров (Actors) - объектов, работающих асинхронно, её можно реализовать многопоточно или кооперативно. но это скорее тема для библиотечного расширения, т.к. представляет частный случай. кстати есть std::atomic<> Alexeis, способов выстрелить в ногу в с++ предостаточно и без многопоточности. но это уже было
|
|||
|
||||
| k0rvin |
|
||||||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 442 Регистрация: 24.1.2010 Репутация: 1 Всего: 5 |
Пример на С реализует агрегирование, а не наследование.
В примере нет никакой инкапсуляции. Инкапсуляция в Си делается например так: counter.h:
counter.c:
main.c:
-------------------- “Object-oriented design is the roman numerals of computing.” — Rob Pike All software sucks |
||||||||||
|
|||||||||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |