![]() |
|
Модераторы: feodorv, GremlinProg, xvr, Fixin |
![]()
|
|
| cubereality |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 75 Регистрация: 28.6.2005 Где: http://artiom.vyr tosu.com Репутация: нет Всего: 1 |
Всем привет!
Помогите пожалуйста решить следующую проблему: У меня есть некий класс A который имеет некую переменную B. Я создаю N таких объектов в памяти, и потом из двух или более разных потоков (многозадачность) меняю вышеупомянутую переменную в каждом конкретном объекте по разному и в разное время. Проблема в том что мне НЕЛЬЗЯ чтобы к этой переменной в одном отдельно взятом созданном в памяти объекте мог получить доступ более чем один поток одновременно. В теории это можно решить при помощи создания отдельного объекта CRYTICAL_SECTION для каждого созданного экземпляра класса и защитой этой критической секцией метода присвоения переменной значения. Но объектов планируется до сотни тысяч в памяти. Как мне поступить в этом случае? С уважением. |
|||
|
||||
| Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: нет Всего: 59 |
А если в самом классе создать метод (учитывая реентерабельность) по изменению этой переменной не получится?
|
|||
|
||||
| cubereality |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 75 Регистрация: 28.6.2005 Где: http://artiom.vyr tosu.com Репутация: нет Всего: 1 |
А поподробнее можно о реентерабельности?
Добавлено @ 22:21 С++ чистый WinAPI. Скажем мне нужно запретить одновременный доступ к переменной класса, но для каждого созданного объекта отдельно. В смысле чтоб блокирование этой переменной не блокировало изменение этой же переменной в других экземплярах этого класса. |
|||
|
||||
| Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: нет Всего: 59 |
Реентерабельность - это внутренняя организация поддержки многопоточности. Т.е. при вызове метода класса (или отдельной функции) из нескольких потоков они (потоки) не предпринимают специальных действий по защите от одновременного доступа к переменным - это реализуется в методе (или функции).
Грубо говоря перенос критических секций из кода потока в код класса. Для потоков остается вызов метода класса, а этот метод сам предпринимает защитные методы (с помощью тех же критический секций) от одновременного доступа к переменной... |
|||
|
||||
| cubereality |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 75 Регистрация: 28.6.2005 Где: http://artiom.vyr tosu.com Репутация: нет Всего: 1 |
А можно конкретный пример кода пожалуйста? В смысле как ЭТО делать?
|
|||
|
||||
| Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: нет Всего: 59 |
Хм... Я пас - это же теория чисто. Примеров нет, я потоки пару раз использовал, но не в таком ключе.
Просто сама идея: запихать критическую секцию не в функцию потока, а в метод класса. Есть объект, есть потоки. Поток вызывает метод объекта, который должен изменить переменную. Так пусть класс сам думает о критической составляющей... |
|||
|
||||
| cubereality |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 75 Регистрация: 28.6.2005 Где: http://artiom.vyr tosu.com Репутация: нет Всего: 1 |
И в таком случае будет защищатся адрес памяти а не условный участок исходного кода?
|
|||
|
||||
| Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: нет Всего: 59 |
Немного не понял, там будет статическая переменная? Одна для всех экземпляров класса?
А вам что конкретно надо блокировать? Я не слышал, чтобы нужно было блокировать код. Обычно блокируется область памяти для исключения одновременного к ней доступа. Существуют критические секции, недопускающие прерывать код, но не для его защаиты, а чтобы он (код) смог нормально поменять данные. Если есть клас и есть куча объектов данного класса, то они помещены в некий контейнер (массив, список...). Потоки, независимо друг от друга изменяют значения некого поля в объектах из этого контейнера. Надо исключить одновременное изменение одного и того же объекта. В каких рамках исключить? Критическая секция недопускает прерывания. Если нужно выполнить дополнительные действия при изменении поля класса - критическую секцию ставим в метод класса, тогда он не прервется пока не изменит переменную. Думаю для более детального обсуждения нужно побольше узнать о конкретной задаче - может быть всем скопом мы ее решим быстро и просто. Это сообщение отредактировал(а) Anikmar - 7.2.2007, 00:32 |
|||
|
||||
| cubereality |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 75 Регистрация: 28.6.2005 Где: http://artiom.vyr tosu.com Репутация: нет Всего: 1 |
Неа, переменная автоматическая, в пределах видимости для каждого объекта по отдельности. Значит можно использовать одну и ту же критическую секцию?
Это сообщение отредактировал(а) cubereality - 7.2.2007, 09:18 |
|||
|
||||
| SergeCpp |
|
|||
![]() ![]() ![]() Профиль Группа: Участник Сообщений: 955 Регистрация: 8.8.2005 Где: At Home Репутация: 10 Всего: 124 |
Рекомендую воспользоваться семейством функций Interlocked*
Некоторые из них отражены в Visual C++ Intrinsics |
|||
|
||||
| Earnest |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 33 Всего: 183 |
Если переменная не длинее DWORD, то проще использовать InterlockedXXX, как было сказано. Для более сложных данных делаем так:
1) В классе заводим переменную CRITICAL_SECTION (это самый простой и быстрый объект синхронизации) 2) В конструкторе класса ее инициализируем (InitializeCriticalSection) 3) Пишем методы Get и Set, в начале каждого EnterCriticalSection, в конце LeaveCriticalSection 4) В методе Get то, что хотим вернуть (скажем, 5й сверху элемент чего-нибудь) между вызовами Enter\Leave копируем во временную переменную, в конце функции - возвращаем эту временную переменную. 5) Естественно при этом нельзя возвращать указатели\ссылки на защищаемые данные, иначе вся защита псу под хвост. 6) Удобно сделать класс-обертку для методов Enter\Leave (конструктор входит в критическую секцию, деструктор - освобождает ее). Это позволяет обойтись одним вызовом, получить exception-safe код и обойтись без временных переменных. Что-то вроде:
Можно пойти дальше и написать простенький макрос (чтобы спрятать из контекста ненужные переменные):
Тогда:
-------------------- ... |
||||||
|
|||||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
Не советую сразу с головой окунаться в секции во всех объектах для такой задачи. Тут явно видна недоработка модели. На каждый маленький экземпляр класса не должно расходоваться слишком много системных ресурсов. В большинстве случаев, при одновременном обращении к данным, достаточно просто организовать конвеер. К тому же, "запирать" конкретную переменную нужно только в двух случаях. Первый - при обращении к перераспределяющемуся массиву, списку, и т.п., чтобы просто избежать повторного использования указателя. И второй - при сложных вычислениях, использующих "смежные", т.е. расшаренные ресурсы, в этом случае есть смысл запирать не сами объекты, где эти вычисления производятся, а только общие ресурсы, да и то, только в том случае, если эти ресурсы могут изменяться в вычислениях. Во всех остальных случаях синхронизация не нужна. -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
![]()
|
| Правила форума "C/C++: Системное программирование и WinAPI" | |
|
|
На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы . Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |