Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > потоки + глобальные функции


Автор: vitaly1979 28.2.2006, 13:32
Как происходят одновременные вызовы какой-либо глобальной для модуля функции из потоков?
Например нужно переопределить функции сокетов:
Код

int send_(....)
{
      ....
      FDSET...; 
      send(....);
      select(...);
      .... 
}
int recv_(....)
{
      ....
      FDSET...; 
      recv(....);
      select(...);
      ....
}
void Thread()
{
      ....
      send_(...);
      recv_(...);
      ....
}


Проблем никаких не будет?

Автор: Romikgy 28.2.2006, 13:44
Синхронизация нужна, если обращение к ф-циям из нескольких потоков будет

Автор: vitaly1979 28.2.2006, 13:49
Это точно?
А как же например несколько потоков вызывают одновременно функции АПИ из ДЛЛ?

Автор: Romikgy 28.2.2006, 13:54
Цитата(vitaly1979 @ 28.2.2006, 12:49 Найти цитируемый пост)
А как же например несколько потоков вызывают одновременно функции АПИ из ДЛЛ?

где ты такое видел?

Автор: vitaly1979 28.2.2006, 14:34
Romikgy, ну как же -)
все АПИ как известно в ДЛЛ, а код ДЛЛ в адресном пространстве всех ниших программ
допустим несколько потоков открывают одновременно разные файлы с помощью CreateFile
код функции CreateFile всего один и по одному адресу
получается что стек функции CreateFile создается для каждого потока отдельно?
и в моем случае будет также?

Автор: takedo 28.2.2006, 14:43
Я так думаю, что функция это кусок кода, по которому проходят потоки. Скорее всего каждый вызов функции ознаменован своими параметрами с которыми поток войдет в этот участок кода. Поэтому, ничего страшного в таких заходах нет. Вот другое дело, если ты в этих функциях оперируешь глобальными переменными, с которыми могут одновременно работать все твои потоки, тогда может наступить попа без синхронизации.
PS.:А вообще то у меня давненько назревает подобный вопросик, нет времени его сформулировать и задать.

Автор: maxim1000 28.2.2006, 14:43
синхронизация нужно при доступе к данным (ну и к устройствам всяким)
само по себе исползование одной и той же функции из разных потоков синхронизации не требует
даже если несколько потоков читают какую-нибудь информацию - тоже необязательно
синхронизация начинает быть нужной, когда кто-то начинает что-то менять...

Автор: Romikgy 28.2.2006, 17:41
Цитата(vitaly1979 @ 28.2.2006, 13:34 Найти цитируемый пост)
получается что стек функции CreateFile создается для каждого потока отдельно?

длл для каждой проги копирует себя в адр. пр-ство программы, но это здесь не причем
Цитата(maxim1000 @ 28.2.2006, 13:43 Найти цитируемый пост)
читают какую-нибудь информацию

при записи .... может быть
Цитата(takedo @ 28.2.2006, 13:43 Найти цитируемый пост)
попа

smile

Автор: maxim1000 28.2.2006, 18:14
Цитата(vitaly1979 @ 28.2.2006, 13:34 Найти цитируемый пост)
получается что стек функции CreateFile создается для каждого потока отдельно?

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

Автор: threef 15.3.2006, 17:08
При вызове функции из потока она использует стек этого потока. Автоматические переменные создаются в стеке - это те, которые внутри функции не описаны как static.
Поэтому, если функция, вызываемая из главной функции потока не оперирует статическими или глобальными переменными, то она может выполняться "одновременно". Такие функции в древности называли повторно входимыми или реентерабельными.
Если функция использует глобальные/статические переменные, то она не является повторно входимой. Необходимо обеспечить явную передачу доступа к глобальной/статической переменной из каждой функции. Для этого используется синхронизация - критические секции, мьютексы, события, ждущие функции и т.п. Функция, работающая с переменной явно захватывает эту переменную, остальные должны подождать освобождения переменной.
Дополнительные "заморочки" возникают при использовании динамических переменных - от захвата кучи процесса до явного назначения потоку собственной кучи.

Автор: takedo 17.3.2006, 07:57
threef,
Цитата

Дополнительные "заморочки" возникают при использовании динамических переменных
- можно поподробнее? Например если я делаю цикл в функции:
Код

int* i;
i = new int;
for(*i=0;*i<10001;*i++)
{
...
}
delete i;

где могут быть проблемы?
PS.: я не ёрничаю, просто очень хочется до конца понять где проблемы. smile

Автор: chipset 17.3.2006, 08:45
Цитата(takedo @ 16.3.2006, 21:57 Найти цитируемый пост)
- можно поподробнее? Например если я делаю цикл в функции:

Код

int* i;
    
i = new int;
    
for(*i=0;*i<10001;*i++)
    
{
    
...
    
}
    
delete i;
...
*i = 0;
while(*i<1001)
{
}
//или вообще
return i;

Автор: Adil' 21.3.2006, 17:55
Цитата(threef @ 15.3.2006, 17:08 Найти цитируемый пост)
Дополнительные "заморочки" возникают при использовании динамических переменных - от захвата кучи процесса до явного назначения потоку собственной кучи.
Эти дополнительные заморочки обычно свалены на голову менеджера памяти компилятора, и самому о них думать не надо.

Автор: takedo 22.3.2006, 15:40
Adil' - даааа. хороший ответ! Но что-то можно понять сиё высказывание и так: "Хороший компилятор - нет проблем, а вот если вы программируете в Крекер С++ или Макдональдс C - то будут проблемы".
Понятно с автоматической памятью, со статической, а вот с динамической - ? пока все раво неа smile

Автор: threef 23.3.2006, 21:44
takedo
Прошу прощения за долгое молчание

Заморочки в потоках при использовании кучи очень простые.
Код


typamoy *x;
...
for(;;)
{
   x= new typamoy(abrakadabra);
   ...
   delete x;
}


и этот цикл внутри функции потока. Чтобы не изгадить кучу(во каламбур!) нужно защититься
HeapLock / Unlock, но это еще не полное решение проблемы. В результате выполнения многих потоков куча может слегка дефрагментироваться, и, так как ею управляет вовсе не компилятор, то и тут нужно соломки подстелить - лучше выделить для разных потоков разные кучи. Отработал поток - удалить его( за ним ?) кучу. И основная куча не так решетится.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)