Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Многопотоковые приложения под Windows

505
18 января 2007 года
vAC
343 / / 28.02.2006
Разрабатывая ПО для многопроцессорных машин под управлением Windows, я столкнулся со множеством проблем,касающихся многопоточности, причину некоторых я так и не выяснил.
Например, есть некоторая функция, выполняющаяся в основном потоке. В ней имеется локальная переменная-структура, затем создавались один или несколько дополнительных потоков, в которые передавался указатель на эту локальную структуру. Затем в этойже функции ожидалось завершение работы потоков. Вот здесь-то я и столкнулся с первой неприятностью. Переменная локальная, значит может учавствовать в оптимизациях,и поэтому переданный указатель будет уже не действителен. Пробему решил либо ключевым словом volatile, либо описанием не локальной, а глобальной структуры.
Еще один глюк схватил,когда передал в поток указатель на класс, и в нем вызывал методы класса по этому указателю. Исправил обращением непосредственно к переменной класса непосредственно, через extern (класс и поток были в разных модулях). Так и не понял причину глюка. Одним словом, подводных камней тьма! Если кто-то имел хороший опыт в подобной теме,прошу поделиться опытом, может литературу какую грамотную посоветуете, как это все "крутиться" на низком уровне, а то алгоритмически вроде все верно, ан нет...
5
18 января 2007 года
hardcase
4.5K / / 09.08.2005
Для начала нужно отказаться от использования структур и использовать ссылки (указатели) на объекты.

Работать с полями объекта через блокирующие вызовы, используя семафоры, мьютексы, события (events). Естественно, инкапсулируя синхронизацию внутри класса. Ещё нужно следить за тем, чтобы не случались dead-lock"и (смертельных объятий) - циклическое ожидание двух и более потоков.
505
18 января 2007 года
vAC
343 / / 28.02.2006
Ну так почему нужно отказаться от указателей, хотельсь бы более детально это понять. Ну насчет работы с полями через семафоры, защелки и события это понятно, без этого никуда. Да и до циклов не доходило. Хорошо, тогда для примера:
Идет обработка одного блока данных, нужно распараллелить этот процесс, как это сделать более корректно? Как здесь без указателя?
1
18 января 2007 года
kot_
7.3K / / 20.01.2000
Не хороший стиль использовать ссылки(указатели) на локальный объект. Никто не гарантирует тебе, что ссылка(указатель) является валидным. В случае потока, тебе самому прийдется отслеживать, что бы объект не разрушился до завершения работы всех потоков.
505
18 января 2007 года
vAC
343 / / 28.02.2006
Цитата: kot_
Не хороший стиль использовать ссылки(указатели) на локальный объект. Никто не гарантирует тебе, что ссылка(указатель) является валидным. В случае потока, тебе самому прийдется отслеживать, что бы объект не разрушился до завершения работы всех потоков.



Ну так это я уже давно понял, это не то что не хороший,я бы даже отнес к неправильным действиям. Как раз структура по этому указателю "исчезала" время от времени

355
18 января 2007 года
<SCORP>
786 / / 21.10.2006
Цитата: vAC
Ну так почему нужно отказаться от указателей



а кто сказал от них отказываться??? просто память надо под объекты в куче выделять. т.е. через оператор new. а потом, есессно, явно их удалять. тогда объекты не будут "самопроизвольно" умирать

3
18 января 2007 года
Green
4.8K / / 20.01.2000
Цитата: vAC

Переменная локальная, значит может учавствовать в оптимизациях,и поэтому переданный указатель будет уже не действителен.


В каких оптимизациях? Почему будет невалиден?
Все будет валидно в пределах срока жизни переменной.
Проблемы лишь с синхронизацией записи значений в эту переменную (впрочем, как и влюбую другую).

Цитата: vAC

Еще один глюк схватил,когда передал в поток указатель на класс, и в нем вызывал методы класса по этому указателю. Исправил обращением непосредственно к переменной класса непосредственно, через extern (класс и поток были в разных модулях). Так и не понял причину глюка.


Опять же, проблема не в указателе, а в разных модулях и синхронизации записи.

Цитата: vAC

Одним словом, подводных камней тьма!


Да нет особых проблем. Просто, обеспечь синхронизацию доступа.

3
18 января 2007 года
Green
4.8K / / 20.01.2000
Цитата: hardcase
Для начала нужно отказаться от использования структур и использовать ссылки (указатели) на объекты.


Фраза не понятна. Разве объекты - это не экземпляры структур?

Цитата: hardcase

Работать с полями объекта через блокирующие вызовы, используя семафоры, мьютексы, события (events).


Только если поле может быть изменено, причем не атомарно.

Цитата: hardcase

Естественно, инкапсулируя синхронизацию внутри класса.


Откуда такая категоричность? Почему бы не использовать внешнюю (про отношению к объекту) синхронизацию?

Цитата: kot_

Не хороший стиль использовать ссылки(указатели) на локальный объект. Никто не гарантирует тебе, что ссылка(указатель) является валидным.


Это не так. Гарантией является ожидание завершения порожденного потока, о чем и говорил автор топика: "Затем в этойже функции ожидалось завершение работы потоков."

5
18 января 2007 года
hardcase
4.5K / / 09.08.2005
Цитата: Green
Разве объекты - это не экземпляры структур?

Извиняйте, привык к C# :o


Цитата: Green
Только если поле может быть изменено, причем не атомарно.

Конечно имелся в виду доступ на запись. :rolleyes:

Цитата: Green
Откуда такая категоричность? Почему бы не использовать внешнюю (про отношению к объекту) синхронизацию?

По-моему, на начальных этапах написания кода так проще мыслить.

505
18 января 2007 года
vAC
343 / / 28.02.2006
Цитата: Green
В каких оптимизациях? Почему будет невалиден?
Все будет валидно в пределах срока жизни переменной.
Проблемы лишь с синхронизацией записи значений в эту переменную (впрочем, как и влюбую другую).

Опять же, проблема не в указателе, а в разных модулях и синхронизации записи.


Да нет особых проблем. Просто, обеспечь синхронизацию доступа.



А зачем тогда volatile, для красоты? и почему бы компилятору не кинуть переменную в регистр процессора?
----
Так в том то и дело,что все эти глюки проявлялись даже если дополнительный поток один, а главный ожидает его завершения, здесь ничего синхронизировать даже не нужно. К тому же если работают несколько потоков, то они пишут в непересекающиеся адреса блока, место под который выделялось оператором new в главном потоке и указатель на него передавался в вспомогательные. Может глюк заключался в другом, сейчас приведу описание:
1. Есть ГЛОБАЛЬНАЯ переменная класса (C)
2. В этом классе выделяется место под блок
3. В одном из методов создается новый поток, которому в передается указатель на этот класс, и происходит ожидание завершения работы.
4. В основной функции потока происходит вызов другого метода тогоже класса по переданному указателю, в котором и осуществлялась запись в блок.
При такой схеме, иногда оказывалось, что в блок ничего не писалось или писалась какая-то белеберда. Исправилось это все, если только в функции потока не использовать переданный указатель, а непосредственно обращаться к переменной класса.
И насчет локальной переменной: часть параметров передавалось через указатель на локальную структуру в функции, где создавался доп. поток, при этом опять же таки значения по этому указателю в потоке оказывались далеки от истенных (опять же не всегда). Исправилось объявлением этой структуры как глобальной. Может это конечно все совпадения, но тем не менее, факт есть факт.

3
19 января 2007 года
Green
4.8K / / 20.01.2000
Цитата: vAC
А зачем тогда volatile, для красоты?


Обратись к документации, что бы узнать зачем:
[QUOTE=MSDN]
The volatile keyword is a type qualifier used to declare that an object can be modified in the program by something such as the operating system, the hardware, or a concurrently executing thread.
[/QUOTE]
Перевожу: для того, чтобы указать, что переменная может быть изменена извне (относительно потока).
Остальная информация в MSDN отвечает на вопросы "как" и "почему", а не "зачем".

Цитата: vAC

и почему бы компилятору не кинуть переменную в регистр процессора?


Потому, что

Цитата: vAC

передавался указатель на эту локальную структуру.


Как ты себе представляешь указатель на переменную в регистре?
Никак? Тогда как ты представляешь себе передачу указателя, который невозможен?
Помогу тебе разрешить этот ребус. Переменная, на которую существует используемый (про неиспользуемый компилятор выдаст предупреждение) указатель, будет существовать в памяти даже при оптимизации. Иначе нельзя гарантировать валидность указателя даже в однопоточном приложении.

Цитата: vAC

Так в том то и дело,что все эти глюки проявлялись даже если дополнительный поток один, а главный ожидает его завершения, здесь ничего синхронизировать даже не нужно. К тому же если работают несколько потоков, то они пишут в непересекающиеся адреса блока, место под который выделялось оператором new в главном потоке и указатель на него передавался в вспомогательные. Может глюк заключался в другом, сейчас приведу описание:
1. Есть ГЛОБАЛЬНАЯ переменная класса (C)
2. В этом классе выделяется место под блок
3. В одном из методов создается новый поток, которому в передается указатель на этот класс, и происходит ожидание завершения работы.
4. В основной функции потока происходит вызов другого метода тогоже класса по переданному указателю, в котором и осуществлялась запись в блок.
При такой схеме, иногда оказывалось, что в блок ничего не писалось или писалась какая-то белеберда. Исправилось это все, если только в функции потока не использовать переданный указатель, а непосредственно обращаться к переменной класса.


М-да... запутанный код. Видимо, где-то что-то наводится....

Цитата: vAC

И насчет локальной переменной: часть параметров передавалось через указатель на локальную структуру в функции, где создавался доп. поток, при этом опять же таки значения по этому указателю в потоке оказывались далеки от истенных (опять же не всегда). Исправилось объявлением этой структуры как глобальной. Может это конечно все совпадения, но тем не менее, факт есть факт.


На счет фактов. Наш сосед, старенький такой дядечка, не курит и не пьет. Не то что бы совсем... Бывает иногда затенется, когда выпьет, но пьет он очень редко. Помниться затянулся выпил он однажды по-молодости, курнул... а в штатах застрелили Кенеди. В следующий раз это совпало с убийством Ленона. Может это конечно все совпадения, но тем не менее, факт есть факт. Сосед с тех пор не курит... не то что бы совсем... :)

505
19 января 2007 года
vAC
343 / / 28.02.2006
Цитата: Green
Обратись к документации, что бы узнать зачем:

Перевожу: для того, чтобы указать, что переменная может быть изменена извне (относительно потока).
Остальная информация в MSDN отвечает на вопросы "как" и "почему", а не "зачем".


Потому, что

Как ты себе представляешь указатель на переменную в регистре?
Никак? Тогда как ты представляешь себе передачу указателя, который невозможен?
Помогу тебе разрешить этот ребус. Переменная, на которую существует используемый (про неиспользуемый компилятор выдаст предупреждение) указатель, будет существовать в памяти даже при оптимизации. Иначе нельзя гарантировать валидность указателя даже в однопоточном приложении.


М-да... запутанный код. Видимо, где-то что-то наводится....


На счет фактов. Наш сосед, старенький такой дядечка, не курит и не пьет. Не то что бы совсем... Бывает иногда затенется, когда выпьет, но пьет он очень редко. Помниться затянулся выпил он однажды по-молодости, курнул... а в штатах застрелили Кенеди. В следующий раз это совпало с убийством Ленона. Может это конечно все совпадения, но тем не менее, факт есть факт. Сосед с тех пор не курит... не то что бы совсем... :)



Конечно насчет лок. переменных все правильно сказано, но я имел ввиду оптимизацию без ссылки (для примера). И в том же МСДН чуть ниже того, что ты написал есть следующее:
Objects declared as volatile are not used in optimizations because their value can change at any time. The system always reads the current value of a volatile object at the point it is requested, even if the previous instruction asked for a value from the same object. Also, the value of the object is written immediately on assignment.
Переводить не буду, именно это я и имел ввиду.

Всетаки я думаю,что все эти глюки пришли по-наследству от других программистов...могло что-то записаться скажем в область, где находится указатель...тогда все ясно, по нему уже нельзя ссылаться

3
19 января 2007 года
Green
4.8K / / 20.01.2000
Это и есть наведенная ошибка, т.е. что-то по ошибке портит где-то память, а сам баг вылазит в другом (совершенно нормальном месте).
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог