powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / разделение ресурсов
21 сообщений из 21, страница 1 из 1
разделение ресурсов
    #34775650
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Написал многопоточное приложение, на XP работает нормально, но на 2003 serv падает, причем странным образом, консолька просто исчезает без сообщений об ошиках и т.п.. Хотя падает очень редко все же очень неприятно. Так вот под подозрением у меня такие моементы:

есть указатель, который может указывать на дин. выделенную память, либо NULL содержит. Проверку типа:
Код: plaintext
1.
if ( p_root->pVal )
...

не стал разделять критическими секциями для более быстрой роботы, т.е. в момент проверки теоретически p_root->pVal может быть изменено др. потоком с NULL на какой-то адрес свежевыделенной памяти. Мне интересно, может ли это привести к краху приложения??

Аналогично:
Код: plaintext
1.
RecursivePass(p_root->sub_tree);

не защищено от изменения др. потоком, тот же вопрос..
...
Рейтинг: 0 / 0
разделение ресурсов
    #34775662
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
т.е. по сути вопрос такой:
Если я читаю значение переменной, и что др. поток может туда писать в любой момент времени, может ил это привести к плачевным результатам?
...
Рейтинг: 0 / 0
разделение ресурсов
    #34775757
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
насколько редко падает?
скомпиль в дебуг
лови вывод
лови код возврата
...
Рейтинг: 0 / 0
разделение ресурсов
    #34775778
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tubrik пишет:
Мне интересно,
> может ли это привести к краху приложения??

Может, и аналогично во втором случае.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
разделение ресурсов
    #34775991
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maXmoнасколько редко падает?
скомпиль в дебуг
лови вывод
лови код возврата

1. можно 50 раз подряд запускать и не упадет, а бывает неск. раз подряд (падает на загрузке, когда начинают обновляться данные в несколько потоков)

2. Чей код возврата, как/чем ловить?

MasterZiv
Tubrik пишет:
Мне интересно,
> может ли это привести к краху приложения??

Может, и аналогично во втором случае.


Что может - понял, но почему, в смысле, каков примерный сценарий приводящий к падению?
p_root->pVal, допустим, равен NULL, что может произойти "плохого", если в момент if ( p_root->pVal ) произойдет запись туда другого значения?

Могу предположить только, что значение с NULL изменится, но "не полностью", в результате произойдет обращение к не той области памяти. Но тогда выходит, что запись значения в переменную не атомарна, т.е. происходит в неск. шагов, которые могу быть прерваны. Глупый сценарий, но другой пока не придумал)
...
Рейтинг: 0 / 0
разделение ресурсов
    #34776055
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TubrikЧто может - понял, но почему, в смысле, каков примерный сценарий приводящий к падению?Указатель сам по себе мало пользы приносит. Ты работаешь на самом деле не с указателем, а с данными находящимися по адресу.
Запись значения в указатель действительно атомарная операция и она не может быть прервана другим потоком, но выделение памяти и уж тем более заполнение этой памяти осмысленными данными - вот это уже совсем не атомарная операция.
К тому же, если у тебя этот самый глобальный указатель может перенаправлятся или обнулятся, то поток должен быть уверен что другой поток не убьет данные по этому адресу пока он с ними работает.
...
Рейтинг: 0 / 0
разделение ресурсов
    #34776302
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tubrik пишет:
> p_root->pVal, допустим, равен NULL, что может произойти "плохого", если
> в момент if ( p_root->pVal ) произойдет запись туда другого значения?

Обращение по адресу 0x00000000. В Win32 например младший мегабайт логической
памяти приложения защищен от любого доступа, так что любое обращение
туда приводит к Access Violaiton.

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

Да, запись в переменную не атомарна. Вообще в С++ пока нет понятия
"атомарная операция", поэтому до выхода следующего стандарта можете
забыть о таких техниках программирования. Используйте средства синхронизации,
предоставляемые операционной системой.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
разделение ресурсов
    #34777056
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlУказатель сам по себе мало пользы приносит. Ты работаешь на самом деле не с указателем, а с данными находящимися по адресу.
Запись значения в указатель действительно атомарная операция и она не может быть прервана другим потоком, но выделение памяти и уж тем более заполнение этой памяти осмысленными данными - вот это уже совсем не атомарная операция.
К тому же, если у тебя этот самый глобальный указатель может перенаправлятся или обнулятся, то поток должен быть уверен что другой поток не убьет данные по этому адресу пока он с ними работает.

Если атомарная, то лучше сначала выделить память, заполнить осмысленнымид данными, а потом просто направить указатель на уже заполненную память.

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

Вообщем решил не гадать, а залочить все нафиг, ибо небольшой выйгрыш во времени потом может выйти боком.
...
Рейтинг: 0 / 0
разделение ресурсов
    #34777186
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Теперь след. вопрос, касающийся этой же темы:)

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

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
void myClass::func_update()
{
	LockData();

	while (get_data())
	{
		// обновление порции данных
	}

	UnlockData();
}

не приемлем. Мне интересно узнать, насколько разумно сделать так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
void myClass::func_update()
{
	while (get_data())
	{
		LockData();
		// обновление порции данных
		//...
		UnlockData();
		Sleep( 0 );		// вроде как должно переключать с этого потока
	}
}

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

И еще вопрос: обновляющий поток сделал THREAD_PRIORITY_BELOW_NORMAL, выходит на планочку меньше стандартного приоритета. Это чтобы он не мешался во время запросов. Есть ли в этом смысл? Т.е. не станет ли он медленнее покидать секцию:
Код: plaintext
1.
2.
3.
4.
		LockData();
		// обновление порции данных
		//...
		UnlockData();
если да, то др. потоки будут его дольше ждать?

Еще вопрос: выставление приоритета THREAD_PRIORITY_BELOW_NORMAL делает его приоритет ниже потоков его процесса или ниже всех потоков системы?
...
Рейтинг: 0 / 0
разделение ресурсов
    #34777677
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tubrik пишет:
> не приемлем. Мне интересно узнать, насколько разумно сделать так:
> void myClass::func_update()
> {
> while (get_data())
> {
> LockData();
> // обновление порции данных
> //...
> UnlockData();
> Sleep(*0*); // вроде как должно переключать с этого потока
> }
> }
>
>
> т.е. намеренно разлочивать данные, чтобы дать другим потокам к ним
> обратиться. Или услышать более интересный вариант..

Это разумно, почему нет. Но только если перед
UnlockData() данные находятся в валидном и консистентном
состоянии. Иначе это делать некорректно.

> И еще вопрос: обновляющий поток сделал THREAD_PRIORITY_BELOW_NORMAL,
> выходит на планочку меньше стандартного приоритета. Это чтобы он не
> мешался во время запросов. Есть ли в этом смысл? Т.е. не станет ли он
> медленнее покидать секцию:

Медленнее не станет покидать. Но если у тебя в системе есть
более высокоприоритетные потоки (что наверняка), то есть риск,
что обновляющий поток никогда не получит управление (или очень
нескоро получит) и не освободит данные.

> если да, то др. потоки будут его дольше ждать?
>

> Еще вопрос: выставление приоритета THREAD_PRIORITY_BELOW_NORMAL делает
> его приоритет ниже потоков его процесса или ниже всех потоков системы?

Всех потоков системы. Точнее так. Есть группы приоритетов. В каждой группе
примерно 3-4 значения приоритета. Есть базовый приоритет процесса. Он
равен среднему значению внутри группы. Приоритеты потоков определяются
относительно базового приоритета процесса. Т.е. ты не можешь напр.
поставить приоритет потока 1. Можешь только PROSESS_BASE-1.
Ну а далее - в системе всегда есть высокоприоритетные процессы,
так что всегда найдутся какие-то с более высоким приоритетом.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
разделение ресурсов
    #34777743
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv
Медленнее не станет покидать. Но если у тебя в системе есть
более высокоприоритетные потоки (что наверняка), то есть риск,
что обновляющий поток никогда не получит управление (или очень
нескоро получит) и не освободит данные.


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

Получается нужно сделать всем одинаковый приоритет и не стараться манипулировать приоритетами (хотябы в случае, когда потоки разделяют один реусрс)??
...
Рейтинг: 0 / 0
разделение ресурсов
    #34778672
teras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Насколько я помню, в WIN32 присвоения указателей типа PVOID и переменных типа (LONG, ULONG, INTPTR, UINTPTR) атомарны, соответственно атомарны и присвоения указателей эквивалентного размера. Так, что скорее всего проблемы не в присвоении, а в алгоритме. По поведению - типичный race conditions. Обычный способ отладки - изучение алгоритма или, если ничего не приходит в голову, расстановка вызовов Sleep(0) (особенно полезно их вызвать перед и после функций ожидания).

Tubrik MasterZiv
Медленнее не станет покидать. Но если у тебя в системе есть
более высокоприоритетные потоки (что наверняка), то есть риск,
что обновляющий поток никогда не получит управление (или очень
нескоро получит) и не освободит данные.


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

Priority Inversion
Priority inversion occurs when two or more threads with different priorities are in contention to be scheduled. Consider a simple case with three threads: thread 1, thread 2, and thread 3. Thread 1 is high priority and becomes ready to be scheduled. Thread 2, a low-priority thread, is executing code in a critical section. Thread 1, the high-priority thread, begins waiting for a shared resource from thread 2. Thread 3 has medium priority. Thread 3 receives all the processor time, because the high-priority thread (thread 1) is waiting for shared resources from the low-priority thread (thread 2). Thread 2 won't leave the critical section, because does not have the highest priority and won't be scheduled.

The scheduler solves this problem by randomly boosting the priority of the ready threads (in this case, the low priority lock-holders). The low priority threads run long enough to exit the critical section, and the high-priority thread can enter the critical section. If the low-priority thread doesn't get enough CPU time to exit the critical section the first time, it will get another chance during the next round of scheduling.

Windows Me/98/95: If a high-priority thread is dependent on a low-priority thread that will not be allowed to run because a medium priority thread is getting all of the CPU time, the system recognizes that the high-priority thread is dependent on the low-priority thread. It will boost the low-priority thread's priority up to the priority of the high-priority thread. This will allow the thread that formerly had the lowest priority to run and release the high-priority thread that was waiting for it.
...
Рейтинг: 0 / 0
разделение ресурсов
    #34778749
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
teras пишет:

> Насколько я помню, в WIN32 присвоения указателей типа PVOID и переменных
> типа (LONG, ULONG, INTPTR, UINTPTR) атомарны, соответственно атомарны и
> присвоения указателей эквивалентного размера.

Откуда такие сведения ?
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
разделение ресурсов
    #34778750
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
teras


То, что система будет поднимать временами его приоритет, дабы не дать бедняге совсем заглохнуть, это понятно. Но вопрос в том, стоит ли ему (потоку обновления) понижать приоритет для того, чтобы он "уступал" время запросам, и не даст ли это побочный эффект в том, что он на более низком приоритете будет дольше "возиться" внутри критической секции, которую, собственно, и ожидают потоки обрабатывающие внешние запросы..
...
Рейтинг: 0 / 0
разделение ресурсов
    #34778805
teras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv
teras пишет:

> Насколько я помню, в WIN32 присвоения указателей типа PVOID и переменных
> типа (LONG, ULONG, INTPTR, UINTPTR) атомарны, соответственно атомарны и
> присвоения указателей эквивалентного размера.

Откуда такие сведения ?
Posted via ActualForum NNTP Server 1.4 Традиционно - MSDN.

Interlocked Variable Access
The interlocked functions provide a simple mechanism for synchronizing access to a variable that is shared by multiple threads. The threads of different processes can use this mechanism if the variable is in shared memory.

Simple reads and writes to properly-aligned 32-bit variables are atomic. In other words, when one thread is updating a 32-bit variable, you will not end up with only one portion of the variable updated; all 32 bits are updated in an atomic fashion. However, access is not guaranteed to be synchronized. If two threads are reading and writing from the same variable, you cannot determine if one thread will perform its read operation before the other performs its write operation.

Simple reads and writes to properly aligned 64-bit variables are atomic on 64-bit Windows. Reads and writes to 64-bit values are not guaranteed to be atomic on 32-bit Windows. Reads and writes to variables of other sizes are not guaranteed to be atomic on any platform.

То есть, операции чтения и записи 32-битных, выровненных значений - атомарны. Выравнивание по умолчанию у VC - или 4 или 8 байт.
...
Рейтинг: 0 / 0
разделение ресурсов
    #34778862
teras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Tubrik teras


То, что система будет поднимать временами его приоритет, дабы не дать бедняге совсем заглохнуть, это понятно. Но вопрос в том, стоит ли ему (потоку обновления) понижать приоритет для того, чтобы он "уступал" время запросам, и не даст ли это побочный эффект в том, что он на более низком приоритете будет дольше "возиться" внутри критической секции, которую, собственно, и ожидают потоки обрабатывающие внешние запросы.. Как следует из приведенного фрагмента, если есть ожидающие потоки с высоким приоритетом - у обрабатывающего потока поднимется приоритет, а значит дольше ждать им не придется (собственно это и называется инверсией приоритета).
Нужно ли поднимать/опускать приоритеты - на такой вопрос ответить не так просто - все зависит от конкретной задачи, распределения нагрузок, различных ограничений. Как правило необходимости в этом нет.
...
Рейтинг: 0 / 0
разделение ресурсов
    #34778903
Sandro_K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TubrikТеперь след. вопрос, касающийся этой же темы:)

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


Тут мне бы хотелось спросить, все ли потоки, обращающиеся к данной структуре изменяют данные.

У меня есть подозрение что некоторые из потоков только читают данные, в этом случае может быть намного эффективнее использовать блокировки на чтение/запись
...
Рейтинг: 0 / 0
разделение ресурсов
    #34778970
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
terasНасколько я помню, в WIN32 присвоения указателей типа PVOID и переменных типа (LONG, ULONG, INTPTR, UINTPTR) атомарны, соответственно атомарны и присвоения указателей эквивалентного размера.Это не совем верно, Win32 здесь не при чем. На самом деле, атомарны операции записи регистра процессора в память. До тех пор пока элементарный тип языка не превышает размер регистра процессора, работа с этим элементарным типом будет атомарной.
Все перечисленные собственные типы платформы Win32 в действительности являются одним и тем же 32-х битным типом. И действительно работа с ними будет атомарной на процессорах с 32+ битными регистрами.
...
Рейтинг: 0 / 0
разделение ресурсов
    #34779079
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandro_K
Тут мне бы хотелось спросить, все ли потоки, обращающиеся к данной структуре изменяют данные.

У меня есть подозрение что некоторые из потоков только читают данные, в этом случае может быть намного эффективнее использовать блокировки на чтение/запись

Обновляющий поток(и) перезаписывают данные если они изменились со времени последнего обновления.

Потоки обрабатывающие запросы только читают данные, если они есть, если их нет, тогда делают запрос на сервер и фактически создают новые данные в кэше. (Само приложение - типа кэш данных, хранит только те, к которым были обращения.)

Соответственно обнуляться данные не могут, они могут либо создаваться, либо изменяться.

Что такое блокировки на чтение/запись?
...
Рейтинг: 0 / 0
разделение ресурсов
    #34779202
teras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl terasНасколько я помню, в WIN32 присвоения указателей типа PVOID и переменных типа (LONG, ULONG, INTPTR, UINTPTR) атомарны, соответственно атомарны и присвоения указателей эквивалентного размера.Это не совем верно, Win32 здесь не при чем. На самом деле, атомарны операции записи регистра процессора в память. Конечно, вы правы, атомарность реализуется на аппаратном уровне. Но это несколько другое. Наличие таких ограничений в спецификации обозначает то, что Win32 никогда не будет портирован под платформы, где присвоение LONG будет не атомарным, а значит этим можно пользоваться, вне зависимости от типа процессора.

TubrikЧто такое блокировки на чтение/запись? Повышение гранулянтности блокировок по уровню доступа. Читатели и писатели взаимоисключающи. При этом в критическую секцию, одновременно может войти несколько читателей. Писатель может быть либо один, либо несколько, в зависимости от реализации. Хороший пример реализации можно найти в pthreads/win32.
...
Рейтинг: 0 / 0
разделение ресурсов
    #34780828
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
teras Повышение гранулянтности блокировок по уровню доступа. Читатели и писатели взаимоисключающи. При этом в критическую секцию, одновременно может войти несколько читателей. Писатель может быть либо один, либо несколько, в зависимости от реализации.

хорошая идея, спасибо)
...
Рейтинг: 0 / 0
21 сообщений из 21, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / разделение ресурсов
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]